前言
栈是一种先进后出的结构,只能对栈顶进行操作,数据入栈、出栈都在栈顶处,换句话说,栈只能对栈顶端进行操作,禁止跳过栈顶插入或删除其它数据。
栈可以简单分为数组栈和链表栈;数组栈设定了空间大小,而链表栈在内存允许的范围内无空间大小限制,通过链表的方式将栈链接起来。
1 链表栈
1.1 数据结构
在单链表的基础结构上(一个数据域和一个指针域),再构建一个栈的结构体,包含一个指向Node节点的指针和一个栈长度计数值(count),top指向栈顶。
你也将栈结构体设计成把count替换成指向栈底的指针,道理都是一样的。
typedef struct _NODE {
int data;
struct _NODE *next; //后继指针
}Node,*Nodelist;
typedef struct _STACK {
Node *top;
int count;
}Stack,*Stackp;
1.2 创建栈
调用malloc函数申请一块栈内存空间,将top指向NULL,表示空栈;count置为0,表示长度为0。
Stackp link_stack_creat()
{
Stack *sta = NULL;
sta = (Stackp)malloc(sizeof(Stack));
if(sta == NULL){
printf("malloc fail.\n");
exit(-1);
}
sta->top = NULL;
sta->count = 0;
return sta;
}
1.3 入栈操作
创建一个新节点,入栈后,新节点的next指针指向top,然后再将top指向新节点处。新节点入栈的过程类似于链表的头插法,栈底的节点next指向NULL;每入栈一个节点,count加一,最后返回指向栈顶的指针。
Stackp link_stack_push(Stackp sta, int data)
{
if(sta == NULL){
printf("push stack error.\n");
exit(-1);
}
Node *p = (Nodelist)malloc(sizeof(Node));
if(p == NULL){
printf("malloc fail.\n");
exit(-1);
}
p->data = data;
p->next = sta->top;
sta->top = p;
sta->count++;
return sta;
}
1.4 出栈操作
出栈就是将栈顶节点移除,并释放掉移除节点的内存空间,将top指向栈顶的下一个节点,count栈长度减一。出栈的时候要判断该栈是否为空,空栈的话就不进行出栈操作。
Stackp link_stack_pop(Stackp sta)
{
Node *p = NULL;
if(sta->top == NULL){
printf("pop stack error.\n");
return sta;
}
else{
p = sta->top;
sta->top = sta->top->next;
free(p);
sta->count--;
}
return sta;
}
1.5 遍历栈操作
遍历栈的数据,并将其数据都打印出来。遍历结束判断条件可以是节点next指针指向NULL。
void link_stack_print(Stackp sta)
{
Node *p = NULL;
if(sta->top == NULL){
printf("stack empty.\n");
return;
}
p = sta->top;
while(1){
printf("data:%d\n",p->data);
if(p->next == NULL){
break;
}
else{
p = p->next;
}
}
}
1.6 示例程序
/****************************************
Fuction:C语言实现链表栈
Time:9/22/2022
Author:Qurry
****************************************/
#include <stdio.h>
#include <stdlib.h>
typedef struct _NODE {
int data;
struct _NODE *next; //后继指针
}Node,*Nodelist;
typedef struct _STACK {
Node *top;
int count;
}Stack,*Stackp;
/******** 创建一个栈 ********/
Stackp link_stack_creat()
{
Stack *sta = NULL;
sta = (Stackp)malloc(sizeof(Stack));
if(sta == NULL){
printf("malloc fail.\n");
exit(-1);
}
sta->top = NULL;
sta->count = 0;
return sta;
}
/*********** 入栈 ************/
Stackp link_stack_push(Stackp sta, int data)
{
if(sta == NULL){
printf("push stack error.\n");
exit(-1);
}
Node *p = (Nodelist)malloc(sizeof(Node));
if(p == NULL){
printf("malloc fail.\n");
exit(-1);
}
p->data = data;
p->next = sta->top;
sta->top = p;
sta->count++;
return sta;
}
/********* 出栈 **********/
Stackp link_stack_pop(Stackp sta)
{
Node *p = NULL;
if(sta->top == NULL){
printf("pop stack error.\n");
return sta;
}
else{
p = sta->top;
sta->top = sta->top->next;
free(p);
sta->count--;
}
return sta;
}
/******** 遍历栈 **********/
void link_stack_print(Stackp sta)
{
Node *p = NULL;
if(sta->top == NULL){
printf("stack empty.\n");
return;
}
p = sta->top;
while(1){
printf("data:%d\n",p->data);
if(p->next == NULL){
break;
}
else{
p = p->next;
}
}
}
void main()
{
int mode = 0, data = 0;
Stack *Top = NULL;
Top = link_stack_creat();
while(1){
printf("please input mode: 0:push 1:pop 2:print 3:exit\n");
scanf("%d",&mode);
switch (mode)
{
case 0:
printf("input push data:");
scanf("%d",&data);
Top = link_stack_push(Top,data);
break;
case 1:
Top = link_stack_pop(Top);
break;
case 2:
link_stack_print(Top);
break;
case 3:
printf("Bye bye.\n");
exit(0);
default:
printf("input mode error.\n");
break;
}
}
}
1.7 Windows下测试结果
2 数组栈
2.1 数组栈结构体设计
在栈结构体里面,定义一个数组,其长度为STACK_LEN(6),top表示栈顶的位置。
#define STACK_LEN 6 //数组栈长度
typedef struct _STACK {
int arr[STACK_LEN];
int top;
}Stack,*Stackp;
2.1 创建栈操作
top初始化为 -1,表示空栈;栈中数组的数据初始化为0。
Stackp array_stack_creat()
{
Stack *sta = NULL;
sta = (Stackp)malloc(sizeof(Stack));
if(sta == NULL){
printf("malloc fail.\n");
exit(-1);
}
memset(sta->arr, 0, STACK_LEN);
sta->top = -1;
return sta;
}
2.2 出、入栈操作
入栈:在栈未满下(sta->top < STACK_LEN),可以执行入栈操作,数组填入数据、top加一;
出栈:在空栈情况下(sta->top == -1),不执行出栈操作;
数组栈的操作总体比链表栈简单明了很多。
void array_stack_push(Stackp sta, int data)
{
if(sta == NULL){
printf("push stack error.\n");
exit(-1);
}
if(sta->top < STACK_LEN -1){
sta->arr[++sta->top] = data;
}
else{
printf("stack is full.\n");
return ;
}
}
void array_stack_pop(Stackp sta)
{
if(sta->top == -1){
printf("stack is empty.\n");
return;
}
sta->arr[sta->top] = 0; //初始化为0
sta->top--;
}
2.3 数组栈总例程
/****************************************
Fuction:C语言实现链表栈
Time:9/23/2022
Author:Qurry
****************************************/
#include <stdio.h>
#include <stdlib.h>
#define STACK_LEN 6 //数组栈长度
typedef struct _STACK {
int arr[STACK_LEN];
int top;
}Stack,*Stackp;
/******** 创建数组栈 ********/
Stackp array_stack_creat()
{
Stack *sta = NULL;
sta = (Stackp)malloc(sizeof(Stack));
if(sta == NULL){
printf("malloc fail.\n");
exit(-1);
}
memset(sta->arr, 0, STACK_LEN);
sta->top = -1;
return sta;
}
/*********** 入栈 ************/
void array_stack_push(Stackp sta, int data)
{
if(sta == NULL){
printf("push stack error.\n");
exit(-1);
}
if(sta->top < STACK_LEN -1){
sta->arr[++sta->top] = data;
}
else{
printf("stack is full.\n");
return ;
}
}
/********* 出栈 **********/
void array_stack_pop(Stackp sta)
{
if(sta->top == -1){
printf("stack is empty.\n");
return;
}
sta->arr[sta->top] = 0; //初始化为0
sta->top--;
}
/******** 遍历栈 **********/
void array_stack_print(Stackp sta)
{
if(sta->top == -1){
return ;
}
for(int i = sta->top; i >= 0; i--){
printf("arr[%d] = %d\n",i,sta->arr[i]);
}
}
void main()
{
int mode = 0, data = 0;
Stack *Sta = NULL;
Sta = array_stack_creat();
while(1){
printf("0:push 1:pop 2:print 3:exit .please input mode: ");
scanf("%d",&mode);
switch (mode)
{
case 0:
printf("input push data:");
scanf("%d",&data);
array_stack_push(Sta,data);
break;
case 1:
array_stack_pop(Sta);
break;
case 2:
array_stack_print(Sta);
break;
case 3:
printf("Bye bye.\n");
free(Sta);
exit(0);
default:
printf("input mode error.\n");
break;
}
}
}