栈的链式存储简称链栈。
在链栈中将链表的头指针和栈顶指针合二为一。
对于链栈来说基本不存在栈满的情况,除非内存以及没有可用空间。对于空栈来说链表原定义是头指针指向空,那么链栈的空其实就是top==NULL的时候。
一、结构
typedef int SElemType;//此处可能是个结构体,练习使用int型足够了
typedef struct stacknode { SElemTypedata; structstacknode * next; }StackNode,* LinkStack;
二、栈的链式存储进栈操作
进栈操作,假设元素值为e新结点是s,top为栈顶指针则进栈操作如下:
算法思路:
1. 分配一个节点s;
2. 将结点值赋值给s->data;
3. 把当前栈顶元素赋值给新结点的直接后继;
4. 将新结点p赋值给栈顶。
三、栈的链式存储出栈操作
出栈操作,假设变量p用来存储要删除的栈顶结点,将栈顶指针下移一位,最后释放p即可。
算法思路:
1. 检查是否是空栈,空栈则返回;
2. 获取栈顶元素,将栈顶赋值给p;
3. 使得栈顶指针下移一位;
4. 释放p
四、时间复杂度
没有任何循环,时间复杂度都是O(1)。
对比一下顺序栈与链栈的时间复杂度均为O(1);空间复杂度上顺序栈需要提前分配一个固定的长度,可能会造成空间的浪费,但是它的优势是存取时候方便,并且链栈要求每个元素都有指针域,这同时也增加了一些内存开销,但是对于栈的长度无限制。所以链栈和顺序栈的区别和线性表中的讨论是一样的:如果栈的使用过程中元素变化不可预料,有时候很小,有时候非常大,那么最好使用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些。
五、代码示例
#include <stdio.h> #include <string.h> #include <malloc.h> #define ERROR -1 #define OK 0 typedef int SElemType;//此处可能是个结构体,练习使用int型足够了 typedef struct stacknode { SElemType data; struct stacknode * next; }StackNode,* LinkStack; //判栈空 int StackEmpty(LinkStack top) { if(top->next==NULL) { return 1; } else { return 0; } } //入栈函数 LinkStack Push(LinkStack top,SElemType e) { StackNode * p = (StackNode *)malloc(sizeof(StackNode)); if(p != NULL) { p->data=e; p->next=top->next;//把当前栈顶元素赋值给新结点的直接后继 top->next=p;//将新结点p赋值给栈顶 } else { printf("分配结点失败\n"); } return top; } //出栈函数 int Pop(LinkStack top) { StackNode * p; SElemType t; if(StackEmpty(top)) { printf("空栈\n"); } else { p = top->next;//将栈顶赋值给p t = p->data; top->next = p->next;//使得栈顶指针下移一位 free(p); } return t; } //打印函数 void PrintStack(LinkStack top) { if(top->next==NULL) { printf("空栈\n"); } else { while(top->next!=NULL) { printf("元素:%d\n",top->next->data); top=top->next; } } } //取栈顶元素 int StackTop(LinkStack top) { if(StackEmpty(top)) { printf("空栈\n"); } return top->next->data; } //栈的长度 int StackLen(LinkStack top) { int len=0; while(top->next!=NULL) { len++; top=top->next; } return len; } //销毁栈 void DestroyStack(LinkStack top) { LinkStack q; while(top) { q=top->next; free(top); top=q; } printf("销毁成功"); } //栈初始化 void InitStack(LinkStack top) { top->next=NULL; } int main() { int i = 0; LinkStack top; top = (LinkStack)malloc(sizeof(StackNode)); //注意 printf("\n=======初始化操作=========\n"); InitStack(top); printf("\n=======入栈操作=========\n"); for(i = 0;i<10;i++) { Push(top,i); //入栈 } printf("栈大小:%d\n",StackLen(top)); printf("\n=======打印栈信息=========\n"); PrintStack(top); //打印栈 printf("\n=======出栈操作=========\n"); if(top->next!=NULL)//出栈 { printf("出栈元素::%d\n",Pop(top)); } else { printf("空栈\n"); } printf("\n=======取栈顶元素=========\n"); if(StackEmpty(top)==1)//取栈顶元素 { printf("空栈\n"); } else { printf("栈顶元素:%d\n",StackTop(top)); } printf("\n=======判断栈是否为空=========\n"); if(StackEmpty(top)==1)//判断栈是否为空 { printf("空栈\n"); } else { printf("不是空栈\n"); } printf("\n=======返回栈的元素个数=========\n"); if(StackEmpty(top)==1)//返回栈的元素个数 { printf("空栈\n"); } else { printf("栈大小:%d\n",StackLen(top)); } printf("\n=======销毁栈=========\n"); DestroyStack(top); return 0; }