栈是一种特殊的线性表,也就是说栈元素具有线性关系,即前驱后继关系。只不过它是一种特殊的线性表而已。定义中说是在线性表的表尾进行插入和删除操作,这里插入是指栈顶,而不是栈底。
栈只能在线性表的一端进行操作
栈顶(Top):允许操作的一端
栈底(Bottom):不允许操作的一端
栈的插入操作,叫做进栈,也称压栈、入栈。
栈的删除操作,叫做出栈,也有的叫做弹栈。
header.h
// // Created by 2NaCl on 2019/2/25. // #ifndef CPRIMERPLUS_HEADER_H #define CPRIMERPLUS_HEADER_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 //CPRIMERPLUS_HEADER_H
#include <stdlib.h> #include <stdio.h> #include <string.h> #include "header.h" int main(){ int ret; int a[10]; SeqStack *stack = NULL; stack = SeqStack_Create(10); if (stack == NULL){ printf("建表出错了"); } for (int i = 0; i < 5; ++i) { a[i]=i+1; SeqStack_Push(stack, &a[i]); printf("Bottom:%d\n", SeqStack_Size(stack)); } printf("Capacity:%d\n", SeqStack_Capacity(stack)); printf("Length:%d\n", SeqStack_Size(stack)); while(SeqStack_Size(stack)>0) { int tmp =*((int *)SeqStack_Pop(stack)); printf("删除了%d", tmp); } system("pause"); }
SeqList.header.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_Insert(SeqList *list,SeqListNode *node,int pos);//向SeqList链表pos的位置插入一个结点node SeqListNode *list_Get(SeqList *list , int pos);//获取pos位置元素 SeqListNode *list_Delete(SeqList *list,int pos);//删除pos位置元素
SeqList.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "header.h" typedef struct SeqList{ int length;//链表实际长度 int capacity;//分配最大的容量 unsigned int *node;//所有的结点所形成的数组 // (动态库内的结点,有多少分配多少,是动态的,所以要用指针指向内存空间内的结点) }tSeqList; SeqList *seqList_Create(int capacity){ tSeqList *tmp = NULL;//既可以在栈分配内存空间,也可以在堆分配内存空间,但是让初始的链表为空 tmp = (tSeqList *) malloc(sizeof(tSeqList)); if(tmp ==NULL) { printf("func SeqList_Create error:%d",0); return NULL; } memset(tmp, 0, sizeof(tSeqList));//总的作用:将已开辟内存空间tmp的首sizeof(tSeqList)个字节的值设为值0 // 根据capacity分配结点空间 tmp->node = (unsigned int *) malloc(sizeof(unsigned int *) * capacity); if (tmp->node == NULL) { printf("func SeqList_Create error:%d",0); return NULL; } tmp->capacity = capacity; tmp->length = 0; return tmp; } void SeqList_Destroy(SeqList *list){ tSeqList *tList = NULL; if (list == NULL) { return; } tList = (tSeqList *) list; if (tList->node != NULL) { free(tList->node); } free(tList); } //清空链表 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 0; } tList = (tSeqList *) list; return tList->length; } int SeqList_Insert(SeqList *list,SeqListNode *node,int pos){ int ret = 0; tSeqList *tList = NULL; if (list == NULL || node == NULL || pos < 0) { return ret; } tList = (tSeqList *) list; //判断插入元素是否满了 if (tList->length == tList->capacity) { printf("满了"); } // 容错修正,pos>length if (pos > tList->length) { pos = tList->length; } //1.元素后移 int i = 0; for (i = (*tList).length; i > pos; --i) { tList->node[i] = (*tList).node[i - 1]; } //2.插入元素 tList->node[i] = (unsigned int) node; tList->length++; } SeqListNode *list_Get(SeqList *list , int pos){ int i = 0; SeqListNode *ret = 0; tSeqList *tList = NULL; if (list == NULL || pos < 0) { printf("产生了错误"); return NULL; } tList = (tSeqList *) list; ret = (void *)tList->node[pos]; return ret; } SeqListNode *list_Delete(SeqList *list,int pos){ SeqListNode *ret = 0; tSeqList *tList = NULL; if (list == NULL || pos < 0) { printf("产生了错误"); return NULL; } tList = (tSeqList *) list; ret = (SeqListNode *) tList->node[pos]; for (int i = pos+1; i <tList->length; ++i) { tList->node[i - 1] = tList->node[i]; } tList->length--; return ret; }
SeqStack.c
#include "header.h" #include <stdio.h> #include <stdlib.h> #include <string.h> //创建栈,相当于创建线性表 SeqStack *SeqStack_Create(int capacity){ return seqList_Create(capacity); } //毁灭栈,相当于销毁线性表 void SeqStack_Destroy(SeqStack *stack){ SeqList_Destroy(stack); } //清空栈,相当于清空线性表 void SeqStack_Clear(SeqStack *stack){ SeqList_Clear(stack); } //Insert int SeqStack_Push(SeqStack *stack,void *item){//因为要向尾部插入元素,所以插入的位置pos=stack.length SeqList_Insert(stack, item, SeqList_Length(stack)); } //Delete void *SeqStack_Pop(SeqStack *stack){//弄出来 list_Delete(stack, SeqList_Length(stack)-1); } //栈顶 void *SeqStack_Top(SeqStack *stack){//检测栈顶 return list_Get(stack, SeqList_Length(stack)-1); } int SeqStack_Size(SeqStack *stack){ return SeqList_Length(stack); } int SeqStack_Capacity(SeqStack *stack){//Capacity return SeqList_Capacity(stack); }
优点:在数据查找(特别是不按照规律排列的数据),时间复杂度教少.效率高. 缺点:插入删除需要移动大量的元素,无法确定内存容量