4.栈
一.stack基本概念
栈是一种 特殊的线性表
栈仅能在线性表的一端进行操作
栈顶(Top):允许操作的一端
栈底(Bottom):不允许操作的一端
stack常用操作
- 创建栈
- 销毁栈
- 清空栈
- 进栈
- 出栈
- 获取栈顶元素
- 获取栈的大小
二.栈的顺序存储设计与实现
2.1 基本概念
2.2 代码实现
栈是一种特殊的线性表,因此可以使用线性表的顺序存储结构予以实现:
seqlist.h
#ifndef __MY_SEQLIST_H__ #define __MY_SEQLIST_H__ typedef void SeqList; typedef void SeqListNode; // 创建线性表 SeqList* SeqList_Create(int capacity); // 销毁线性表 void SeqList_Destroy(SeqList* list); // 清空线性表 void SeqList_Clear(SeqList* list); // 获取当前线性表长度 int SeqList_Length(SeqList* list); // 获取当前线性表容量 int SeqList_Capacity(SeqList* list); // 向线性表插入元素 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos); // 获取线性表元素 SeqListNode* SeqList_Get(SeqList* list, int pos); // 删除线性表中指定元素 SeqListNode* SeqList_Delete(SeqList* list, int pos); #endif
seqlist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "seqlist.h" typedef struct _tag_SeqList { int capacity; int length; unsigned int *arr; }TSeqList; // 创建线性表 SeqList* SeqList_Create(int capacity) { TSeqList *ret = NULL; if (capacity <= 0) return NULL; ret = (TSeqList*)malloc(sizeof(TSeqList)+sizeof(unsigned int)*capacity); if (ret != NULL) { memset(ret, 0, sizeof(sizeof(TSeqList)+sizeof(unsigned int)*capacity)); ret->capacity = capacity; ret->length = 0; ret->arr = (unsigned int *)(ret + 1); } return ret; } // 销毁线性表 void SeqList_Destroy(SeqList* list) { if (list != NULL) free(list); } // 清空线性表 void SeqList_Clear(SeqList* list) { TSeqList *tList = NULL; if (list == NULL) return; tList = (TSeqList*)list; tList->length = 0; } // 获取当前线性表长度 int SeqList_Length(SeqList* list) { TSeqList *tList = NULL; if (list == NULL) return -1; tList = (TSeqList*)list; return tList->length; } // 获取当前线性表容量 int SeqList_Capacity(SeqList* list) { TSeqList *tList = NULL; if (list == NULL) return -1; tList = (TSeqList*)list; return tList->capacity; } // 向线性表插入元素 int SeqList_Insert(SeqList* list, SeqListNode* node, int pos) { TSeqList *tList = NULL; int i = 0; if (list == NULL || node == NULL || pos < 0) return -1; tList = (TSeqList*)list; if (tList->length >= tList->capacity) return -2; if (pos >= tList->capacity) return -3; if (pos >= tList->length) pos = tList->length; // 插入算法 for (i = tList->length; i>pos; i--) { // 把前面的元素向后移 tList->arr[i] = tList->arr[i-1]; } tList->arr[pos] = (unsigned int)node; // 将传入的指针使用16进制整数保存 tList->length++; return 1; } // 获取线性表元素 SeqListNode* SeqList_Get(SeqList* list, int pos) { TSeqList *tList = NULL; SeqListNode *ret = NULL; if (list == NULL || pos < 0) return NULL; tList = (TSeqList*)list; ret = (SeqListNode*)tList->arr[pos]; return ret; } // 删除线性表中指定元素 SeqListNode* SeqList_Delete(SeqList* list, int pos) { SeqListNode *ret = NULL; TSeqList *tList = NULL; int i = 0; if (list == NULL || pos < 0) return NULL; tList = (TSeqList*)list; if (pos >= tList->length) return NULL; // 记录待删除的元素 ret = (SeqListNode*)tList->arr[pos]; // 删除算法 for (i = pos + 1; i < tList->length; i++) { tList->arr[i - 1] = tList->arr[i]; } tList->length--; return ret; }
seqstack.h
#ifndef __MY_SEQSTACK_H__ #define __MY_SEQSTACK_H__ typedef void SeqStack; // 创建栈 SeqStack* SeqStack_Create(int capacity); // 销毁栈 void SeqStack_Destroy(SeqStack *stack); // 清空栈 void SeqStack_Clear(SeqStack *stack); // 将元素压入栈底 int SeqStack_Push(SeqStack *stack, void *item); // 弹出栈顶元素 void* SeqStack_Pop(SeqStack *stack); // 获取当前栈顶元素 void* SeqStack_Top(SeqStack *stack); // 获取当前栈的大小 int SeqStack_Size(SeqStack *stack); // 获取当前栈的容量 int SeqStack_Capacity(SeqStack *stack); #endif
seqstack.c
#include "seqstack.h" #include "seqlist.h" // 创建栈 SeqStack* SeqStack_Create(int capacity) { return SeqList_Create(capacity); } // 销毁栈 void SeqStack_Destroy(SeqStack *stack) { return SeqList_Destroy(stack); } // 清空栈 void SeqStack_Clear(SeqStack *stack) { SeqList_Clear(stack); } // 将元素压入栈底,相当于向线性表中插入元素(尾插法) int SeqStack_Push(SeqStack *stack, void *item) { return SeqList_Insert(stack, item, SeqList_Length(stack)); } // 弹出栈顶元素,相当于从线性表中删除元素,即:删除最后一个元素 void* SeqStack_Pop(SeqStack *stack) { return SeqList_Delete(stack, SeqList_Length(stack) - 1); } // 获取当前栈顶元素 void* SeqStack_Top(SeqStack *stack) { return SeqList_Get(stack, SeqList_Length(stack) - 1); } // 获取当前栈的大小 int SeqStack_Size(SeqStack *stack) { return SeqList_Length(stack); } // 获取当前栈的容量 int SeqStack_Capacity(SeqStack *stack) { return SeqList_Capacity(stack); }
test.c
#include <stdio.h> #include <stdlib.h> #include "seqstack.h" typedef struct _Student { char name[64]; int age; }Student; int main() { int a[20], i = 0; SeqStack *stack = NULL; stack = SeqStack_Create(20); if (stack != NULL) { for (i = 0; i < 10; i++) { a[i] = i + 1; SeqStack_Push(stack, a + i); } // 获取栈顶元素 int *pTop = (int*)SeqStack_Top(stack); printf("current top value is: %d\n", *pTop); printf("\n"); printf("current stack capacity is: %d\n",SeqStack_Capacity(stack)); printf("\n"); printf("current stack size is: %d\n",SeqStack_Size(stack)); // 弹出栈顶元素 SeqStack_Pop(stack); int *top = (int*)SeqStack_Top(stack); printf("current top valus is: %d\n",*top); // 销毁栈 SeqStack_Destroy(stack); } system("pause"); return 0; }
运行结果:
current top value is: 10
current stack capacity is: 20
current stack size is: 10
current top valus is: 9
请按任意键继续. . .
三.栈的链式存储设计与实现
3.1 基本概念
3.2 代码实现
linklist.h
#ifndef __MY_LINKLIST_H__ #define __MY_LINKLIST_H__ #define DLL_API __declspec(dllexport) //_declspec(dllexport):导出标志 typedef void LinkList; typedef struct _tag_LinkListNode { struct _tag_LinkListNode* next; // 当前节点需要指向下一个节点的地址 }LinkListNode; LinkList* LinkList_Create(); void LinkList_Destroy(LinkList *list); void LinkList_Clear(LinkList *list); int LinkList_Length(LinkList *list); int LinkList_Insert(LinkList *list, LinkListNode *node, int pos); LinkListNode* LinkList_Get(LinkList *list, int pos); LinkListNode* ListList_Delete(LinkList *list, int pos); #endif
linklist.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "linklist.h" typedef struct _tag_LinkList { LinkListNode header; // 链表中需要包含一个头节点 int length; }TLinkList; // 创建链表 LinkList* LinkList_Create() { TLinkList *ret = (TLinkList*)malloc(sizeof(TLinkList)); if (ret == NULL) return NULL; memset(ret, 0, sizeof(TLinkList)); ret->header.next = NULL; ret->length = 0; return ret; } // 销毁链表 void LinkList_Destroy(LinkList *list) { if (list != NULL) { free(list); } } // 清空链表 void LinkList_Clear(LinkList *list) { TLinkList *tList = NULL; if (list == NULL) return; tList = (TLinkList*)list; tList->header.next = NULL; tList->length = 0; } // 获取当前链表长度 int LinkList_Length(LinkList *list) { TLinkList *tList = NULL; if (list == NULL) return -1; tList = (TLinkList*)list; return tList->length; } // 向当前链表插入数据 int LinkList_Insert(LinkList *list, LinkListNode *node, int pos) { TLinkList *tList = NULL; LinkListNode *current = NULL; int i = 0; tList = (TLinkList*)list; // 过滤非法参数 if (list == NULL || pos < 0) { return -1; } /* * 插入要点 *1.让新插入的元素节点指向原有位置的元素节点 *2.修改原有位置的前一个元素节点的指向(更新指向为新插入的元素节点) */ // 准备环境让辅助指针变量 指向链表头节点 current = &tList->header; // 将当前链表的节点移动到待插入节点的前一个节点的位置(假如待插入的位置是3,则移动到2号位置) for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; // 将辅助节点运动到指定位置(待插入位置的前一个节点) } // 让新插入的元素节点指向原有位置的元素节点 node->next = current->next; current->next = node; tList->length++; return 0; } LinkListNode* LinkList_Get(LinkList *list, int pos) { TLinkList *tList = NULL; int i = 0; LinkListNode *current = NULL; LinkListNode *ret = NULL; tList = (TLinkList *)list; // 过滤非法参数 if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } current = &tList->header; // 将辅助指针变量运行到待获取元素的前一个节点 for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; } ret = current->next; return ret; } LinkListNode* ListList_Delete(LinkList *list, int pos) { TLinkList *tList = NULL; tList = (TLinkList *)list; LinkListNode *current = NULL; LinkListNode *ret = NULL; int i = 0; // 过滤非法参数 if (list == NULL || pos < 0 || pos >= tList->length) { return NULL; } // 移动辅助指针变量 current = &tList->header; for (i = 0; i < pos && (current->next != NULL); i++) { current = current->next; } ret = current->next; // 将待删除位置的前一个节点的指向连接到删除位置节点的指向 current->next = ret->next; // 将链表长度-1 tList->length--; return ret; }
linkstack.h
#ifndef __MY_LINKSTACK_H__ #define __MY_LINKSTACK_H__ typedef void LinkStack; // 创建栈 LinkStack* LinkStack_Create(); // 销毁栈 void LinkStack_Destroy(LinkStack* stack); // 清空栈 void LinkStack_Clear(LinkStack* stack); // 将元素压入栈 int LinkStack_Push(LinkStack* stack, void* item); // 弹出栈顶元素 void* LinkStack_Pop(LinkStack* stack); // 返回栈顶元素 void* LinkStack_Top(LinkStack* stack); // 返回元素个数 int LinkStack_Size(LinkStack* stack); #endif
linkstack.c
#include <stdlib.h> #include "linkstack.h" #include "linklist.h" // 占位结构 与node节点大小一样 typedef struct _tag_LinkStackNode { LinkListNode node; void *item; }TLinkStackNode; // 创建栈 LinkStack* LinkStack_Create() { return LinkList_Create(); } // 销毁栈(注意destroy的时候,需要把栈中的所有元素都清空) void LinkStack_Destroy(LinkStack* stack) { if (stack == NULL) return; LinkStack_Clear(stack); // 释放内存 LinkList_Destroy(stack); } // 清空栈 void LinkStack_Clear(LinkStack* stack) { if (stack == NULL) return; while (LinkStack_Size(stack) > 0) { LinkStack_Pop(stack); // 这个函数中有内存释放函数 } } // 将元素压入栈 int LinkStack_Push(LinkStack* stack, void* item) { int ret = 0; TLinkStackNode *pTe = (TLinkStackNode*)malloc(sizeof(TLinkStackNode)); if (pTe == NULL) return -1; pTe->item = item; // 头插法,向线性表中插入元素,插入元素的时候需要构造业务节点,采用头插法,保证先进后出 ret = LinkList_Insert(stack, (LinkListNode*)pTe, 0); if (ret != 0) // 插入失败 { free(pTe); } return ret; } // 弹出栈顶元素 void* LinkStack_Pop(LinkStack* stack) { void *ret = NULL; TLinkStackNode *pTmp = NULL; pTmp = (TLinkStackNode*)ListList_Delete(stack, 0); if (pTmp == NULL) return NULL; ret = pTmp->item; free(pTmp); return ret; } // 返回栈顶元素 void* LinkStack_Top(LinkStack* stack) { void *ret = NULL; TLinkStackNode *tmp = NULL; tmp = (TLinkStackNode*)LinkList_Get(stack, 0); if (tmp == NULL) return NULL; ret = tmp->item; return ret; } // 返回元素个数 int LinkStack_Size(LinkStack* stack) { return LinkList_Length(stack); }
test.c
#include <stdio.h> #include <stdlib.h> #include "linkstack.h" typedef struct _Student{ char name[64]; int age; }Student; int main() { Student s1; Student s2; Student s3; Student s4; Student s5; Student s6; s1.age = 11; s2.age = 12; s3.age = 13; s4.age = 14; s5.age = 15; s6.age = 16; LinkStack *stack = LinkStack_Create(); if (stack != NULL) { // 压栈 LinkStack_Push(stack, &s1); LinkStack_Push(stack, &s2); LinkStack_Push(stack, &s3); printf("current stack size is: %d\n",LinkStack_Size(stack)); printf("\n"); // 栈顶元素 Student *pStu = NULL; pStu = LinkStack_Top(stack); printf("current stack element is %d\n",pStu->age); printf("\n"); // 弹出栈顶元素 LinkStack_Pop(stack); pStu = LinkStack_Top(stack); printf("current stack element is %d\n", pStu->age); printf("\n"); // 清空栈 LinkStack_Clear(stack); printf("current stack size is: %d\n",LinkStack_Size(stack)); printf("\n"); // 销毁栈 LinkStack_Destroy(stack); } system("pause"); return 0; }
运行结果:
current stack size is: 3
current stack element is 13
current stack element is 12
current stack size is: 0
请按任意键继续. . .