一 写在开头
1.1 本文内容
数据结构栈的实现。
二 栈的实现
不多说了,请直接看代码。
1 // stack.h 2 3 /* 为了使用bool */ 4 #include <stdbool.h> 5 6 #ifndef _H_STACK_H 7 #define _H_STACK_H 8 9 /* 数据类型 */ 10 typedef char type; 11 12 /* 栈结点 */ 13 typedef struct tsNode 14 { 15 type data; 16 struct tsNode *next; 17 } Node; 18 19 /* 栈类型 */ 20 typedef struct tsStack 21 { 22 Node *top; 23 unsigned int size; 24 } Stack; 25 26 /* 初始化Stack */ 27 Stack * 28 StackInit(void); 29 30 /* 判断栈是否为空。为空返回true,否则返回false */ 31 bool 32 IsEmpty(Stack *); 33 34 /* 入栈操作 */ 35 void 36 StackPush(Stack *, type); 37 38 /* 出栈操作 */ 39 type 40 StackPop(Stack *); 41 42 /* 取得栈顶元素 */ 43 type 44 GetTop(Stack *); 45 #endif
1 // stack.c 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <stdbool.h> 6 #include "stack.h" 7 8 /* 功能:栈初始化 9 * 输入:无 10 * 输出:一个指向Stack型的指针,指针所指对象已被初始化 11 */ 12 Stack * 13 StackInit(void) 14 { 15 Stack *s = NULL; 16 17 s = (Stack *)malloc(sizeof(Stack)); 18 if (s == NULL) 19 exit(EXIT_FAILURE); 20 s->top = NULL; 21 s->size = 0; 22 return s; 23 } 24 25 /* 功能:判断栈是否为空。为空返回true,否则返回false 26 * 输入:一个指向Stack型的指针 27 * 输出:一个bool型变量 28 */ 29 bool 30 IsEmpty(Stack *s) 31 { 32 /* s未被初始化 */ 33 if (s == NULL) 34 exit(EXIT_FAILURE); 35 else 36 return ((s->size) == 0); 37 } 38 39 /* 功能:入栈操作 40 * 输入:一个指向Stack型的指针,一个type型待入栈变量 41 * 输出:无 42 */ 43 void 44 StackPush(Stack *s, type x) 45 { 46 Node *temp = (Node *)malloc(sizeof(Node)); 47 48 if (temp == NULL) 49 exit(EXIT_FAILURE); 50 temp->data = x; 51 52 /* 若s未被初始化 */ 53 if (s == NULL) 54 exit(EXIT_FAILURE); 55 temp->next = s->top; 56 s->top = temp; 57 s->size = (s->size) + 1; 58 } 59 60 /* 功能:出栈操作 61 * 输入:一个指向Stack型的指针 62 * 输出:被出栈的元素 63 */ 64 type 65 StackPop(Stack *s) 66 { 67 Node *p = NULL; 68 type r; 69 70 if (IsEmpty(s)) 71 exit(EXIT_FAILURE); 72 p = s->top->next; 73 r = s->top->data; 74 free(s->top); 75 s->top = p; 76 s->size = (s->size) - 1; 77 return r; 78 } 79 80 /* 功能:返回栈顶元素 81 * 输入:一个指向Stack型的指针 82 * 输出:栈顶元素 83 */ 84 type 85 GetTop(Stack *s) 86 { 87 if (IsEmpty(s)) 88 exit(EXIT_FAILURE); 89 return s->top->data; 90 }
1 #include <stdio.h> 2 #include "stack.h" 3 4 int main(int argc, char *argv[]) 5 { 6 Stack *s = StackInit(); 7 8 /* test passed 9 printf("s->top = %p ", s->top); 10 printf("s->size = %u ", s->size); 11 printf("s is empty: "); 12 IsEmpty(s) ? printf("yes ") : printf("no "); 13 */ 14 15 /* test passed 16 StackPush(s, 'h'); 17 StackPush(s, 'e'); 18 StackPush(s, 'l'); 19 StackPush(s, 'l'); 20 StackPush(s, 'o'); 21 printf("s is empty: "); 22 IsEmpty(s) ? printf("yes ") : printf("no "); 23 printf("s->size = %u ", s->size); 24 25 while ((s->size) > 0) 26 { 27 printf("%c ", StackPop(s)); 28 } 29 printf("s is empty: "); 30 IsEmpty(s) ? printf("yes ") : printf("no "); 31 */ 32 33 /* test passed 34 StackPush(s, 'h'); 35 StackPush(s, 'e'); 36 StackPush(s, 'l'); 37 StackPush(s, 'l'); 38 StackPush(s, 'o'); 39 while (IsEmpty(s) == false) 40 { 41 printf("%c ", GetTop(s)); 42 StackPop(s); 43 } 44 printf("s is empty: "); 45 IsEmpty(s) ? printf("yes ") : printf("no "); 46 */ 47 48 // 栈的内存组织情况 - pass 49 /* 当s为空栈时内存组织情况 50 * p s - 0x602010 51 * p s->top - 0x0 52 * p s->size - 0 53 */ 54 55 StackPush(s, 'h'); 56 /* 当s中有一个值为'h'的元素时内存组织情况 57 * p s - 0x602010 58 * p s->top - 0x602030 59 * p s->size - 1 60 * p s->top->data - 'h' 61 * p s->top->next - 0x0 62 */ 63 64 StackPush(s, 'e'); 65 /* 当s中有两个元素时内存组织情况 66 * p s - 0x602010 67 * p s->top - 0x602050 68 * p s->size - 2 69 * p s->top->data - 'e' 70 * p s->top->next - 0x602030 71 * p s->top->next->data - 'h' 72 * p s->top->next->next - 0x0 73 */ 74 75 StackPop(s); 76 /* 当将栈顶元素弹出后内存组织情况 77 * p s - 0x602010 78 * p s->top - 0x602030 79 * p s->size - 1 80 * p s->top->data - 'h' 81 * p s->top->next - 0x0 82 */ 83 84 return 0; 85 }
注意:为了成功编译包含了stack.h的主程序,你需要使用下面的命令。也即必须将stack.c编译成目标文件,供链接程序链接使用,否则链接程序将报错。不同于C标准库的使用,因为C标准库默认采用动态链接的方式,所用标准库中的函数均已经被编译好了,放在特定的目录下面,链接程序只需去目录中找相对应的目标文件即可。这里我们必须将stack.c编译成目标文件,供主程序链接时使用。
gcc main.c stack.c
三 栈的一个应用实例
来做题吧!题目来源在此。需要说明的是下面的代码质量不好,因为代码是在上面的栈代码基础上拼凑而来的。为了记录每个字符在输入字符串中的位置,在栈结点中添加了一个index字段用于记录结点位置。算法原理很简单:将每一个字符入栈,判断入栈的字符是否为右括号(')'),如果是则将左右括号出栈并将二者在字符串中的位置按题目要求的顺序打印出来即可。
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <stdbool.h> 5 #define ARR_MAX_LEN 128 6 static char array[ARR_MAX_LEN]; 7 8 /* 数据类型 */ 9 typedef char type; 10 11 /* 栈结点 */ 12 typedef struct tsNode 13 { 14 int index; 15 type data; 16 struct tsNode *next; 17 } Node; 18 19 /* 栈类型 */ 20 typedef struct tsStack 21 { 22 Node *top; 23 unsigned int size; 24 } Stack; 25 26 /* 初始化Stack */ 27 Stack * 28 StackInit(void); 29 30 /* 判断栈是否为空。为空返回true,否则返回false */ 31 bool 32 IsEmpty(Stack *); 33 34 /* 入栈操作 */ 35 void 36 StackPush(Stack *, int, type); 37 38 /* 出栈操作 */ 39 type 40 StackPop(Stack *); 41 42 /* 取得栈顶元素 */ 43 Node * 44 GetTop(Stack *); 45 46 /* 功能:栈初始化 47 * 输入:无 48 * 输出:一个指向Stack型的指针,指针所指对象已被初始化 49 */ 50 Stack * 51 StackInit(void) 52 { 53 Stack *s = NULL; 54 55 s = (Stack *)malloc(sizeof(Stack)); 56 if (s == NULL) 57 exit(EXIT_FAILURE); 58 s->top = NULL; 59 s->size = 0; 60 return s; 61 } 62 63 /* 功能:判断栈是否为空。为空返回true,否则返回false 64 * 输入:一个指向Stack型的指针 65 * 输出:一个bool型变量 66 */ 67 bool 68 IsEmpty(Stack *s) 69 { 70 /* s未被初始化 */ 71 if (s == NULL) 72 exit(EXIT_FAILURE); 73 else 74 return ((s->size) == 0); 75 } 76 77 /* 功能:入栈操作 78 * 输入:一个指向Stack型的指针,一个type型待入栈变量 79 * 输出:无 80 */ 81 void 82 StackPush(Stack *s, int index, type x) 83 { 84 Node *temp = (Node *)malloc(sizeof(Node)); 85 86 if (temp == NULL) 87 exit(EXIT_FAILURE); 88 temp->index = index; 89 temp->data = x; 90 91 /* 若s未被初始化 */ 92 if (s == NULL) 93 exit(EXIT_FAILURE); 94 temp->next = s->top; 95 s->top = temp; 96 s->size = (s->size) + 1; 97 } 98 99 /* 功能:出栈操作 100 * 输入:一个指向Stack型的指针 101 * 输出:被出栈的元素 102 */ 103 type 104 StackPop(Stack *s) 105 { 106 Node *p = NULL; 107 type r; 108 109 if (IsEmpty(s)) 110 exit(EXIT_FAILURE); 111 p = s->top->next; 112 r = s->top->data; 113 free(s->top); 114 s->top = p; 115 s->size = (s->size) - 1; 116 return r; 117 } 118 119 /* 功能:返回栈顶元素 120 * 输入:一个指向Stack型的指针 121 * 输出:栈顶元素 122 */ 123 Node * 124 GetTop(Stack *s) 125 { 126 if (IsEmpty(s)) 127 exit(EXIT_FAILURE); 128 return s->top; 129 } 130 131 int 132 main(int argc, char *argv[]) 133 { 134 //freopen("in.txt", "r", stdin); 135 int i, len, temp; 136 Stack *s = StackInit(); 137 138 scanf("%s", array); 139 len = strlen(array); 140 for (i = 0; i < len; i++) 141 { 142 StackPush(s, i, array[i]); 143 if ((GetTop(s))->data == ')') 144 { 145 temp = GetTop(s)->index; 146 StackPop(s); 147 printf("%d %d ", (GetTop(s))->index, temp); 148 StackPop(s); 149 } 150 } 151 152 //fclose(stdin); 153 return 0; 154 }
四 版本二
相较于上面的版本一有细微的改动,增加了函数ClearStack()用于清空栈。
1 /* stack.h */ 2 3 #ifndef _H_STACK_H 4 #define _H_STACK_H 5 6 #include <stdbool.h> 7 8 typedef char dtype; // 数据类型 9 10 typedef struct Node // 节点类型 11 { 12 dtype data; 13 struct Node * next; 14 } tNode; 15 16 typedef struct Stack // 栈类型 17 { 18 tNode * top; 19 unsigned long long size; 20 } tStack; 21 22 /* 栈初始化 */ 23 tStack * 24 StackInit(void); 25 26 /* 判断栈是否为空。为空返回true;否则返回false */ 27 bool 28 IsEmpty(tStack *); 29 30 /* 入栈 */ 31 void 32 StackPush(tStack *, dtype); 33 34 /* 出栈 */ 35 dtype 36 StackPop(tStack *); 37 38 /* 取得栈顶元素 */ 39 dtype 40 GetTop(tStack *); 41 42 /* 清空栈 */ 43 void 44 ClearStack(tStack *); 45 46 #endif
1 /* stack.c */ 2 3 #include <stdlib.h> 4 #include <stdbool.h> 5 #include "stack.h" 6 7 /* 描述:栈初始化 8 * 输入:无 9 * 输出:一个指向tStack型的指针,指针所指向对象已被初始化 10 */ 11 tStack * 12 StackInit(void) 13 { 14 tStack * s = (tStack *)malloc(sizeof(tStack)); 15 if (s == NULL) 16 exit(EXIT_FAILURE); 17 s->top = NULL; 18 s->size = 0; 19 return s; 20 } 21 22 /* 描述:判断栈是否为空。为空返回true,否则返回false 23 * 输入:一个指向tStack型的指针 24 * 输出:true或者false 25 */ 26 bool 27 IsEmpty(tStack * s) 28 { 29 /* s未被初始化 */ 30 if (s == NULL) 31 exit(EXIT_FAILURE); 32 return (s->size) == 0; 33 } 34 35 /* 描述:入栈操作 36 * 输入:一个指向tStack型的指针,一个dtype型待入栈变量 37 * 输出:无 38 */ 39 void 40 StackPush(tStack * s, dtype x) 41 { 42 /* s未被初始化 */ 43 if (s == NULL) 44 exit(EXIT_FAILURE); 45 tNode * temp = (tNode *)malloc(sizeof(tNode)); 46 if (temp == NULL) 47 exit(EXIT_FAILURE); 48 temp->data = x; 49 temp->next = s->top; 50 s->top = temp; 51 s->size = (s->size) + 1; 52 } 53 54 /* 描述:出栈操作 55 * 输入:一个指向tStack型的指针 56 * 输出:一个dtype型的被出栈元素 57 */ 58 dtype 59 StackPop(tStack * s) 60 { 61 tNode * p = NULL; 62 dtype r; 63 64 if (IsEmpty(s)) 65 exit(EXIT_FAILURE); 66 p = s->top->next; 67 r = s->top->data; 68 free(s->top); 69 s->top = p; 70 s->size = (s->size) - 1; 71 return r; 72 } 73 74 /* 描述:取得栈顶元素而不出栈 75 * 输入:一个指向tStack型的指针 76 * 输出:栈顶元素 77 */ 78 dtype 79 GetTop(tStack * s) 80 { 81 if (IsEmpty(s)) 82 exit(EXIT_FAILURE); 83 return s->top->data; 84 } 85 86 /* 描述:清空栈 87 * 输入:一个指向tStack型的指针 88 * 输出:无 89 */ 90 void 91 ClearStack(tStack * s) 92 { 93 /* s未被初始化 */ 94 if (s == NULL) 95 exit(EXIT_FAILURE); 96 while (IsEmpty(s) == false) 97 StackPop(s); 98 free(s); 99 }
1 /* tstack.c */ 2 3 #include <stdio.h> 4 #include "stack.h" 5 6 int main(int argc, char *argv[]) 7 { 8 tStack * s = StackInit(); 9 10 // test pass 11 // printf("s->top = %p ", s->top); 12 // printf("s->size = %llu ", s->size); 13 // printf("s is empty: "); 14 // IsEmpty(s) ? printf("yes ") : printf("no "); 15 16 // test pass 17 // StackPush(s, 'h'); 18 // StackPush(s, 'e'); 19 // StackPush(s, 'l'); 20 // StackPush(s, 'l'); 21 // StackPush(s, 'o'); 22 // printf("s is empty: "); 23 // IsEmpty(s) ? printf("yes ") : printf("no "); 24 // printf("s->size = %llu ", s->size); 25 // 26 // while ((s->size) > 0) 27 // { 28 // printf("%c ", StackPop(s)); 29 // } 30 // printf("s is empty: "); 31 // IsEmpty(s) ? printf("yes ") : printf("no "); 32 33 // test pass 34 // StackPush(s, 'h'); 35 // StackPush(s, 'e'); 36 // StackPush(s, 'l'); 37 // StackPush(s, 'l'); 38 // StackPush(s, 'o'); 39 // while (IsEmpty(s) == false) 40 // { 41 // printf("%c ", GetTop(s)); 42 // StackPop(s); 43 // } 44 // printf("s is empty: "); 45 // IsEmpty(s) ? printf("yes ") : printf("no "); 46 47 // 栈的内存组织情况 48 /* 当s为空栈时内存组织情况 49 * p s - 0x602010 50 * p s->top - 0x0 51 * p s->size - 0 52 */ 53 54 // StackPush(s, 'h'); 55 /* 当s中有一个值为'h'的元素时内存组织情况 56 * p s - 0x602010 57 * p s->top - 0x602030 58 * p s->size - 1 59 * p s->top->data - 'h' 60 * p s->top->next - 0x0 61 */ 62 63 // StackPush(s, 'e'); 64 /* 当s中有两个元素时内存组织情况 65 * p s - 0x602010 66 * p s->top - 0x602050 67 * p s->size - 2 68 * p s->top->data - 'e' 69 * p s->top->next - 0x602030 70 * p s->top->next->data - 'h' 71 * p s->top->next->next - 0x0 72 */ 73 74 // StackPop(s); 75 /* 当将栈顶元素弹出后内存组织情况 76 * p s - 0x602010 77 * p s->top - 0x602030 78 * p s->size - 1 79 * p s->top->data - 'h' 80 * p s->top->next - 0x0 81 */ 82 83 // StackPop(s); 84 /* 当将栈元素全弹出后内存组织情况 85 * p s - 0x602010 86 * p s->top - 0x0 87 * p s->size - 0 88 */ 89 90 // test pass 91 // StackPush(s, 'h'); 92 // StackPush(s, 'e'); 93 // ClearStack(s); 94 /* 当栈s被清空后,变量s被清除出了上下文中 */ 95 96 return 0; 97 }