栈
基本操作:入栈、出栈、取栈顶元素
基本特性:先进后出
注意:栈本身不能遍历,不能打印,我们在代码中实现的打印只是为了检查代码的正确性
具体操作的详细解释在代码中会有注释。
1.顺序栈:
在结构体内定义一个变量以
使用malloc申请内存,从而实现将顺序表的固定长度修改为可动态扩容
SeqStack.h
#pragma once #include <stdio.h> #include <stddef.h> #include <stdlib.h> #define SHOW_NAME printf("===================%s================\n",__FUNCTION__); typedef char SeqStackType; typedef struct SeqStack { SeqStackType* data; size_t size; size_t capacity;//data指向内存的最大容量,即顺序表中数组的MAXSIZE的替代品 }SeqStack;
SeqStack.c
#include "SeqStack.h" void SeqStackInit(SeqStack* stack)//初始化 { if(stack == NULL) { return; } stack->size = 0; stack->capacity = 1000;//元素个数,而非内存字节数 stack->data = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType)); return; } void SeqStackDestroy(SeqStack* stack)//销毁 { free(stack->data); stack->size = 0; stack->capacity = 0; return; } void SeqStackResize(SeqStack* stack)//扩容函数 { if(stack == NULL)//双重保证 { return; } if(stack->size < stack->capacity) { return; } stack->capacity = stack->capacity *2 +1;//扩容规则根据自己喜好定,这里+1是避免传入的capacity为0 //申请新内存 SeqStackType* new_ptr = (SeqStackType*)malloc(stack->capacity * sizeof(SeqStackType)); //将原来数据拷贝到新申请空间里(不推荐使用realloc) size_t i = 0; for(; i<stack->size; ++i) { new_ptr[i] = stack->data[i]; } free(stack->data);//释放旧内存 stack->data = new_ptr; return; } void SeqStackPush(SeqStack* stack, SeqStackType value)//元素进栈 { if(stack == NULL) { return; } if(stack->size >= stack->capacity)//栈已满,需要扩容 { SeqStackResize(stack);//调用扩容函数 } stack->data[stack->size++] = value; return; } void SeqStackPop(SeqStack* stack)//元素出栈 { if(stack == NULL) return; if(stack->size == 0)//空栈 return; stack->size--;//把最后一个元素置为无效即可 return; } int SeqStackGetTop(SeqStack* stack, SeqStackType* top)//取栈顶元素,返回两信息:是否取成功;用输出型参数top返回取得的栈顶元素 { if(stack == NULL || top == NULL) return 0; if(stack->size == 0) return 0; *top = stack->data[stack->size-1];//这里不能写stack->size--,会改变size值 return 1; } void SeqStackPrint(SeqStack* stack,const char* msg)//打印栈内元素,为了检测释放入栈、出栈,实际上是不能打印栈的 { printf("%s\n",msg); if(stack == NULL) return; size_t i = 0; for(; i<stack->size; ++i) { printf("[%c] ",stack->data[i]); } printf("\n"); return; } void TestInit() { SHOW_NAME; SeqStack stack; SeqStackInit(&stack); printf("size : excepted is 0,actual is %d\n",stack.size); printf("capacity : excepted is 1000,actual is %d\n",stack.capacity); return; } void TestDestroy() { SHOW_NAME; SeqStack stack; SeqStackInit(&stack); SeqStackDestroy(&stack); return; } void TestPush() { SHOW_NAME; SeqStack stack; SeqStackInit(&stack); SeqStackPush(&stack,'a'); SeqStackPush(&stack,'b'); SeqStackPush(&stack,'c'); SeqStackPush(&stack,'d'); SeqStackPush(&stack,'e'); SeqStackPush(&stack,'f'); SeqStackPrint(&stack,"入栈六个元素"); return; } void TestPop() { SHOW_NAME; SeqStack stack; SeqStackInit(&stack); SeqStackPush(&stack,'a'); SeqStackPush(&stack,'b'); SeqStackPush(&stack,'c'); SeqStackPush(&stack,'d'); SeqStackPrint(&stack,"入栈六个元素"); SeqStackPop(&stack); SeqStackPop(&stack); SeqStackPrint(&stack,"出栈两个元素"); SeqStackPop(&stack); SeqStackPop(&stack); SeqStackPrint(&stack,"再出栈两个元素"); SeqStackPop(&stack); SeqStackPrint(&stack,"再出栈一个元素"); return; } void TestGetTop() { SHOW_NAME; SeqStack stack; SeqStackInit(&stack); SeqStackPush(&stack,'a'); SeqStackPush(&stack,'b'); SeqStackPush(&stack,'c'); SeqStackPush(&stack,'d'); SeqStackPush(&stack,'e'); SeqStackPush(&stack,'f'); SeqStackPrint(&stack,"入栈六个元素"); SeqStackType top; int ret = SeqStackGetTop(&stack,&top); if(ret == 1) { printf("获取栈顶元素成功,栈顶元素为 %c\n",top); } else { printf("获取栈顶元素失败\n"); } return; } int main() { TestInit(); TestDestroy(); TestPush(); TestPop(); TestGetTop(); return 0; }
2.链式栈:
利用与单链表类似的方法实现链式栈
LinkStack.h
#pragma once #include <stdio.h> #include <stddef.h> #include <stdlib.h> #define SHOW_NAME printf("\n===================%s================\n",__FUNCTION__); typedef char LinkStackType; //typedef struct LinkNode //{ // LinkStackType data; // LinkNode* next; //}LinkNode; typedef struct LinkStack//带头结点的链栈 { LinkStackType data; struct LinkStack* next; }LinkStack;
扫描二维码关注公众号,回复:
165584 查看本文章
LinkStack.c
#include "LinkStack.h" LinkStack* CreateNode(LinkStackType value)//创建新结点 { LinkStack* new_node = (LinkStack*)malloc(sizeof(LinkStack)); new_node->data = value; new_node->next = NULL; return new_node; } void LinkStackInit(LinkStack** stack)//初始化 { *stack = NULL; } void LinkStackPush(LinkStack** stack,LinkStackType value)//元素入栈(尾插) { if(stack == NULL) return; if(*stack == NULL)//空栈 { *stack = CreateNode(value); return; } LinkStack* cur = *stack; while(cur->next != NULL) { cur = cur->next; } LinkStack* new_node = CreateNode(value); cur->next = new_node; new_node->next = NULL; return; } void DestroyNode(LinkStack* node)//销毁结点 { free(node);//每一个malloc对应一个free } void LinkStackPop(LinkStack** stack)//元素出栈(尾删) { if(stack == NULL)//非法 return; if(*stack == NULL)//空栈 return; if((*stack)->next == NULL)//仅有一个元素 { DestroyNode(*stack); *stack = NULL; return; } LinkStack* cur = *stack; LinkStack* pre = NULL;//最后一个元素出栈后,还需将其next置空 while(cur->next != NULL) { pre = cur; cur = cur->next; } pre->next = NULL;//链表的最后一个元素的next一定为NULL DestroyNode(cur); } int LinkStackGetTop(LinkStack* stack,LinkStackType* top)//取栈顶元素(链表的最后一个元素) { if(stack == NULL || top == NULL)//空栈 return 0; LinkStack* cur = stack; while(cur->next != NULL) { cur = cur->next; } *top = cur->data; return 1; } void LinkStackDestroy(LinkStack** stack)//销毁栈 { if(stack == NULL)//非法操作 return; if(*stack == NULL) return; LinkStack* cur = *stack; while(cur != NULL) { LinkStack* to_delete = cur; cur = cur->next; DestroyNode(to_delete); } *stack = NULL; } void LinkStackPrint(LinkStack* stack,const char* msg)//打印栈中元素,检测一下代码是否正确 { printf("[%s]\n",msg); LinkStack* cur = stack; while(cur != NULL) { printf("[%c] ",cur->data); cur = cur->next; } printf("\n"); return; } void TestInit() { SHOW_NAME; LinkStack* stack; LinkStackInit(&stack); } void TestPush() { SHOW_NAME; LinkStack* stack; LinkStackInit(&stack); LinkStackPush(&stack,'a'); LinkStackPush(&stack,'b'); LinkStackPush(&stack,'c'); LinkStackPush(&stack,'d'); LinkStackPush(&stack,'e'); LinkStackPrint(stack,"入栈五个元素"); } void TestPop() { SHOW_NAME; LinkStack* stack; LinkStackInit(&stack); LinkStackPush(&stack,'a'); LinkStackPush(&stack,'b'); LinkStackPush(&stack,'c'); LinkStackPush(&stack,'d'); LinkStackPrint(stack,"入栈五个元素"); LinkStackPop(&stack); LinkStackPop(&stack); LinkStackPrint(stack,"出栈两个元素"); LinkStackPop(&stack); LinkStackPop(&stack); LinkStackPrint(stack,"再出栈两个元素"); LinkStackPop(&stack); LinkStackPrint(stack,"再出栈一个元素"); } void TestGetTop() { SHOW_NAME; LinkStack* stack; LinkStackInit(&stack); LinkStackPush(&stack,'a'); LinkStackPush(&stack,'b'); LinkStackPush(&stack,'c'); LinkStackPush(&stack,'d'); LinkStackPrint(stack,"入栈四个元素"); int ret = 0; LinkStackType top; ret = LinkStackGetTop(stack,&top); if(ret == 1) printf("取得栈顶元素为 %c\n",top); else printf("未取得栈顶元素\n"); LinkStackPop(&stack); LinkStackPop(&stack); LinkStackPrint(stack,"出栈两个元素"); ret = LinkStackGetTop(stack,&top); if(ret == 1) printf("取得栈顶元素为 %c\n",top); else printf("未取得栈顶元素\n"); LinkStackPop(&stack); LinkStackPop(&stack); LinkStackPrint(stack,"再出栈两个元素"); ret = LinkStackGetTop(stack,&top); if(ret == 1) printf("取得栈顶元素为 %d\n",top); else printf("未取得栈顶元素\n"); } void TestDestroy() { SHOW_NAME; LinkStack* stack; LinkStackInit(&stack); LinkStackDestroy(&stack); } int main() { TestInit(); TestPush(); TestPop(); TestGetTop(); TestDestroy(); return 0; }