橘生淮南

记录学习中的点点滴滴

0%

《数据结构》C语言版——栈链

顺序栈是分配一段连续的内存空间,需要两个指针,即指针top与指针base,指针top指向栈顶,指针base指向栈底,而链栈每个结点的地址是不连续的,所以只需要一个栈顶指针即可,相比于单链表,栈链的操作只能在栈顶进行。

入栈前,旧的栈顶结点是新入栈结点的后继结点,栈顶指针重新指向新入栈的结点;
出栈前,新的栈顶结点是即将出栈结点的后继结点,栈顶指针指向出栈结点的后继(即指向新的栈顶结点,把出栈结点释放);

空口无凭,纸上的概念都显得苍白无力,让我们把代码开起来,慢慢细品!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdio.h>
#include <malloc.h>
#include <assert.h>//断言——如果条件返回错误,则终止程序执行
typedef int ElemType;//定义元素类型为int型,即为存放整型数据的栈链
/*给出结点结构*/
typedef struct StackNode
{
ElemType data;//数据域
struct StackNode *next;//指针域(指向下一个结点的地址)
}ListNode,*pNode;//定义结点类型,定义结点的指针类型

/*给出链栈结构*/
typedef struct ListStack
{
pNode top;//指针top指向栈顶元素
size_t size;//结点的个数
}ListStack;

/*初始化链栈*/
void InitStack(ListStack *s)
{
s->top=(StackNode*)malloc(sizeof(StackNode)); //栈顶指针指向新申请的结点
assert(s->top!=NULL);//判断申请空间是否为空
s->top = NULL;//栈顶指针初始化
s->size=0;//栈中元素初始化为0个
}

/*链栈是否为空*/
bool IsEmptyStack(ListStack *s)//给出链栈的位置
{
if(s->size == 0)
return true;
else
return false;
}

/*入链栈*/
void PushStack(ListStack *s, ElemType x)//给出链栈的位置和即将入栈的元素
{
StackNode *p=(StackNode*)malloc(sizeof(StackNode));//指针p指向申请的新结点
assert(p!=NULL);
p->data = x;//入栈的元素保存新结点的数据域
p->next = s->top;//新结点的指针域保存栈顶指针的地址
s->top = p;//栈顶指针重新指向新结点
s->size++;//栈中元素增加
}

/*出链栈*/
void PopStack(ListStack *s, ElemType *v)
{
StackNode *p=s->top;//指针p指向栈顶
*v=s->top->data;//指针v带回栈顶元素
s->top=s->top->next;//栈顶指针指向栈顶结点的后继结点
free(p);//释放栈顶结点
s->size--;//栈中元素减少
}

/*展示链栈*/
void ShowStack(ListStack *s)
{
StackNode *p=s->top;//指针p指向栈顶
printf("链栈中的数据元素:");
while(p!=NULL)//栈不为空,执行
{
printf("%d->",p->data);
p = p->next;//p指向下一个结点
}
printf("\n");
}

/*取栈顶指针*/
void GetTopStack(ListStack *s,ElemType *v)
{
if(s->top==NULL)
return;
else
*v=s->top->data;//指针v带回栈顶元素
}

/*栈长*/
int LengthStack(ListStack *s)
{
return s->size;
}

/*清空栈链*/
void ClearStack(ListStack *s)
{
StackNode *p=s->top;//指针p指向栈顶结点
while(p!=NULL)
{
s->top=p->next;//栈顶指针指向栈顶结点的后继结点
free(p);//释放栈顶结点
p=s->top;//指针p重新指向栈顶结点
}
s->top = NULL;//否则栈顶指针置空
s->size = 0;//栈中长度置0
}

/*销毁栈链*/
void DestroyStack(ListStack *s)
{
ClearStack(s);
free(s->top);//销毁最初创建的结点
s->top=NULL;//预防野指针
}

void main()
{
ListStack st;
ElemType e;
InitStack(&st);
if(IsEmptyStack(&st))
printf("栈为空,初始化成功\n\n");
else
printf("栈非空!\n\n");
printf("入栈\n");
for(int i=0;i<5;i++)
{
PushStack(&st,i);
}
ShowStack(&st);
printf("\n");
int k=LengthStack(&st);
printf("栈的长度为:%d \n\n",k);
GetTopStack(&st,&e);
printf("栈顶元素为:%d \n",e);
printf("\n");
printf("出栈\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
printf("\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
printf("\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
printf("\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
printf("\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
printf("\n");
PopStack(&st,&e);
printf("出栈的元素为:%d \n",e);
ShowStack(&st);
ClearStack(&st);
DestroyStack(&st);
}

运行结果:
在这里插入图片描述

欢迎关注我的其它发布渠道

-------------本文结束感谢您的阅读-------------