【数据结构】之栈(C语言描述)
栈(Stack)是编程中最常用的数据结构之一。
栈的特点是“后进先出”,就像堆积木一样,堆的时候要一块一块堆到最上面,拆的时候需要从最上面一块一块往下拆。栈的原理也一样,只不过它的操作不叫堆和拆,而是叫入栈(或压栈)和出栈(或弹栈)。栈要求我们只能在栈顶(最上面的元素)处进行增加和删除。
栈可以用顺序表示法(顺序栈)和链式表示法(链栈)。由于栈只需要在一端增删节点,不需要在中间某处增删节点,因此即使栈在应用中大多数做的是增删操作,顺序栈虽然在增删操作时略微逊色于链栈(因为可能会扩容),但其存储密度要高于链栈,因此二者在性能方面可以说是各有各的好处。
下面的代码是使用 C语言 描述的链栈的代码。
栈的头文件 Stack.h 中的代码:
/** * 栈(链栈): * 本程序中栈的存储方式:栈顶->节点->节点->...->栈底。即:栈顶是第一个元素 */ #include <Constant.h> // 栈中存储的数据的类型 typedef int ElemType; // 栈中的节点的数据结构体 typedef struct StackNode { ElemType value; // 栈节点中存储的数据的值 struct StackNode* nextNode; // 下一个节点 } StackNode; // 栈的数据结构体 typedef struct Stack { StackNode* data; // 栈中存储的所有节点 int length; // 栈的长度 StackNode* topNode; // 栈顶元素节点 } Stack; // 初始化一个空栈 Status initStack(Stack* S) { S->data = (StackNode*)malloc(sizeof(StackNode)); if(S->data == NULL) { printf("初始化栈失败!\n"); return FAILURE; } S->length = 0; S->topNode = NULL; return SUCCESS; } // 销毁栈 Status destroyStack(Stack* S) { StackNode* tmpNode; if(S->data == NULL) { printf("栈不存在,销毁失败!\n"); return FAILURE; } while(S->topNode != NULL && S->topNode != S->data) { tmpNode = S->topNode; S->topNode = S->topNode->nextNode; free(tmpNode); } S->data = NULL; S->length = 0; S->topNode = NULL; return SUCCESS; } // 清空栈 Status clearStack(Stack* S) { StackNode* tmpNode; if(S->data == NULL) { printf("栈不存在,清空失败!\n"); return FAILURE; } if(S->topNode == NULL) { return SUCCESS; } while(S->topNode != S->data) { tmpNode = S->topNode; S->topNode = S->topNode->nextNode; free(tmpNode); } S->topNode = NULL; S->length = 0; return SUCCESS; } // 判断栈是否为空 Status isStackEmpty(Stack* S) { if(S->data == NULL) { printf("栈不存在!\n"); exit(1); } if(S->length == 0) { return TRUE; } return FALSE; } // 获取栈中元素的长度 int getStackLength(Stack* S) { if(S->data == NULL) { printf("栈不存在!\n"); exit(1); } return S->length; } // 查看栈顶元素的值 ElemType getTopElem(Stack* S) { if(S->data == NULL) { printf("栈不存在,获取元素失败!\n"); exit(1); } if(S->topNode == NULL) { printf("栈是空栈,获取元素失败!\n"); exit(1); } return S->topNode->value; } // 元素入栈 Status push(Stack* S, ElemType e) { StackNode* tmpNode; if(S->data == NULL) { printf("栈不存在,元素入栈失败!\n"); return FAILURE; } tmpNode = (StackNode*)malloc(sizeof(StackNode)); if(tmpNode == NULL) { printf("元素入栈失败!\n"); return FAILURE; } tmpNode->value = e; S->length++; if(S->topNode == NULL) { S->topNode = tmpNode; S->topNode->nextNode = S->data; return SUCCESS; } tmpNode->nextNode = S->topNode; S->topNode = tmpNode; return SUCCESS; } // 元素出栈 StackNode* pop(Stack* S) { StackNode* tmpNode; if(S->data == NULL) { printf("栈不存在,元素出栈失败!\n"); exit(1); } if(S->topNode == NULL) { printf("栈是空栈,元素出栈失败!\n"); return NULL; } tmpNode = S->topNode; S->topNode = S->topNode->nextNode; if(S->topNode == S->data) { S->topNode = NULL; } tmpNode->nextNode = NULL; S->length--; return tmpNode; } // 遍历栈中的元素 void traverseStack(Stack* S) { StackNode* tmpNode; if(S->data == NULL) { printf("栈不存在,遍历失败!\n"); exit(1); } if(S->topNode == NULL) { printf("栈是空栈,遍历失败!\n"); exit(1); } printf("遍历栈:"); tmpNode = S->topNode; while(tmpNode != S->data) { printf("%-4d", tmpNode->value); tmpNode = tmpNode->nextNode; } printf("\n"); } // 栈的测试函数 int testStack() { // 数据声明 Stack stack; StackNode* node; int i; // 初始化栈 if(initStack(&stack) == SUCCESS) { printf("初始化栈成功!\n"); } // 判断栈是否是空栈 printf("栈是否为空栈?%s\n", isStackEmpty(&stack) == TRUE ? "是" : "否"); // 元素入栈 for(i = 1; i <= 5; i++) { if(push(&stack, i) == SUCCESS) { printf("元素%d入栈成功!\n", i); } } // 遍历栈中的元素 traverseStack(&stack); // 元素出栈 node = pop(&stack); if(node != NULL) { printf("元素%d成功出栈!\n", node->value); } // 遍历栈中的元素 traverseStack(&stack); // 查看栈顶元素的值 printf("栈顶元素的值是:%d\n", getTopElem(&stack)); // 获取栈的长度 printf("栈的当前长度:%d\n", getStackLength(&stack)); // 清空栈 if(clearStack(&stack) == SUCCESS) { printf("清空栈成功!\n"); } // 销毁栈 if(destroyStack(&stack) == SUCCESS) { printf("销毁栈成功!\n"); } return 0; }
常量类 Constant.h 中定义了一些常量,其代码如下:
#include <stdio.h> #include <stdlib.h> #define TRUE 1 #define FALSE 0 #define SUCCESS 1 #define FAILURE 0 typedef int Status;
主函数所在的文件 main.c 中的代码如下:
#include <Stack.h> int main() { testStack(); return 0; }
运行结果如下:
初始化栈成功!
栈是否为空栈?是
元素1入栈成功!
元素2入栈成功!
元素3入栈成功!
元素4入栈成功!
元素5入栈成功!
遍历栈:5 4 3 2 1
元素5成功出栈!
遍历栈:4 3 2 1
栈顶元素的值是:4
栈的当前长度:4
清空栈成功!
销毁栈成功!
Process returned 0 (0x0) execution time : 0.016 s
Press any key to continue.