栈(链式存储)
栈的链式存储书上没有,没有!但是不能影响我们前进的脚步。盘他!
栈的链式存储实际上就是单链表,仅仅在尾部操作,这就是重点。
1.结构
链式存储,当然要典型的链表的结构
typedef int SElemType;
typedef struct SingleList
{
SElemType data;
struct SingleList* next;
} SList;
然后再添加一个栈的结构,这个全局结构记录了栈的关键信息。
typedef struct
{
SList* top;
SList* base;
int stack_size;
} SQS;
2.重点
- 先创建一个头节点,这个节点就是栈底。在顺序存储中栈底占用了一个地址,也就是一个字节,链式存储中先开辟了一个节点,这个节点就是栈底,多大?sizeof(Slist),应该是8个字节。
- 压入栈一个元素,临时开辟一个节点的内存,不像顺序存储的时候先开辟一段连续的空间。
- 理论上没有栈满的情况,这个取决于内存的大小。顺序存储是一点一点开辟固定大小空间,栈满经常发生,就要扩容。链式存储因为是动态开辟空间,所以基本不会发生栈满的情况。
- 由于是链式存储,不能使用 top++、top–这种操作!!!!
- 要注意链式存储的形态,有图有真相。
可以看到节点的地址不连续,出栈的时候也是一样。结合下边的代码看吧。
3.代码
sqstacklist.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
typedef int SElemType;
typedef struct SingleList
{
SElemType data;
struct SingleList* next;
} SList;
typedef struct
{
SList* top;
SList* base;
int stack_size;
} SQS;
typedef int Status;
#define ERROR 0;
#define OK 1;
//初始化链表,建立一个空头
Status Init_stack(SQS* s);
//压栈
Status Push(SQS* s, SElemType e);
//出栈
Status Pop(SQS* s, SElemType* e);
//打印链表
void PrintSingleList(SList* sl);
sqstacklist.c
#pragma once
#include"sqstacklist.h"
extern SQS ssq;
Status Init_stack(SQS* s)
{
SList* lnew;
lnew = (SList*)malloc(sizeof(SList));
if (!lnew)
{
printf("内存分配失败。");
return ERROR;
}
lnew->next = NULL;
s->base = lnew;
s->top = lnew;
s->stack_size = 0;
return OK;
}
Status Push(SQS* s, SElemType e)
{
SList* lnew;
lnew = (SList*)malloc(sizeof(SList));
if (!lnew)
{
printf("内存分配失败。");
return ERROR;
}
lnew->data = e;
lnew->next = NULL;
s->top->next = lnew;
s->top = lnew;
s->stack_size++;
return OK;
}
//出栈
Status Pop(SQS* s, SElemType* e)
{
SList* ll;
int i;
if (s->stack_size <= 0)
{
printf("栈空额。弹。。弹。。。弹个毛线。\n");
return ERROR;
}
ll = s->base;
for (i = 0; i < s->stack_size - 1; i++)
{
ll = ll->next;
}
*e = s->top->data;
free(s->top);
s->top = ll;
s->top->next = NULL;
s->stack_size--;
return OK;
}
void PrintSingleList(SList* sl)
{
int i = 0;
//带有头节点,跳过头结点
sl = sl->next;
while (sl)
{
printf("\t%d:\t%d\n", i++, sl->data);
sl = sl->next;
}
}
测试代码
#include <stdio.h>
#include<stdlib.h>
#include"sqstacklist.h"
SQS ssq;
int main()
{
int i,n,j;
printf("初始化----\n");
Init_stack(&ssq);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d.\n",ssq.base,ssq.top,ssq.stack_size);
printf("压栈----\n");
Push(&ssq, 1);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size,ssq.top->data);
Push(&ssq, 2);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
Push(&ssq, 3);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
Push(&ssq, 4);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
Push(&ssq, 5);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, ssq.top->data);
//PrintSingleList(ssq.base);
printf("弹栈----\n");
j = ssq.stack_size;
for (i = 0; i < j; i++)
{
Pop(&ssq, &n);
printf("s.base:0x%x,\ts.top:0x%x,\ts.size=%d,\tdata=%d\n", ssq.base, ssq.top, ssq.stack_size, n);
}
Pop(&ssq, &n);
system("pause");
}