链栈是指采用链式储存结构实现的栈。通常链栈是用单链表来表示。链栈的节点结构与单链表的结构相同,定义链栈的储存结构为:
typedef int Status;
typedef struct Node{
int data; //结点的数据域
struct Node *next; //结点的指针域
}Node,*LinkList;
由于栈的主要操作是在栈顶插入和删除,显然以链表的头部作为栈顶是最方便的,而且没必要像单链表那样为了操作方便附加一个头结点。
下面给出链栈部分操作的实现。
1.初始化
链栈的初始化操作就是构造一个空栈。因为没必要设头结点,所以直接将栈顶指针置空即可。
Status Init_Stack(LinkList &S)
{
S = (LinkList)malloc(sizeof(Node));
if(!S)
return ERROR;
S->next = NULL;
return OK;
}
2.入栈
和顺序栈入栈操作不同的是,链栈在入栈前不需要判断栈是否满,只需要为入栈元素动态分配个节点空间。
1)为入栈元素e分配空间,用指针p指向。
2)捡个新节点数据域置为e。
3)将新节点插入栈顶。
4)修改栈顶指针为p。
Status Push_Stack(LinkList &S,int e)
{
LinkList p = (LinkList)malloc(sizeof(Node));
if(!p)
return ERROR;
p->data = e;
p->next = S->next;
S->next = p;
return OK;
}
3.出栈
顺序栈一样链栈在出栈前,也需要判断栈是否为空。不同的是,链栈在出栈后,需要释放出栈元素的栈顶空间。
1)判断栈是否为空,若空则返回error。
2)将栈顶元素赋给e。
3)临时保存栈顶元素是空间,以备释放。
4)修改栈顶指针,指向新的栈顶元素。
5)释放原栈顶元素的空间。
Status Pop_Stack(LinkList &S)
{
LinkList p = S->next;
if(!p)
return ERROR;
S->next = p->next;
free(p);
return OK;
}
4.取栈顶元素
与顺序栈一样,当栈非空时,此操作返回当前的栈顶元素值。
//功能:取栈顶元素
int Top_Stack(LinkList S)
{
LinkList p = S->next;
if(!p)
return ERROR;//万一出栈的就是-1呢,所以不一定return ERROR
return p->data;
}
接下来附上源代码,其中还有其他功能实现都有注释,各位老板点点赞!
#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR -1
typedef int Status;
typedef struct Node{
int data; //结点的数据域
struct Node *next; //结点的指针域
}Node,*LinkList;
void ShowMenu()
{
printf("\n");
printf("\n****************链栈基本操作****************\n\n");
printf("\t\t1. 数据入栈\n");
printf("\t\t2. 数据出栈\n");
printf("\t\t3. 读取栈顶元素\n");
printf("\t\t4. 读取栈中所有元素\n");
printf("\t\t5. 清除栈中数据\n");
printf("\t\t6. 销毁栈\n");
printf("\t\t7. 是否为栈空\n");
printf("\t\t0. 退出系统\n");
printf("\n****************链栈基本操作****************\n\n");
printf("\n");
}
//功能:带表头的链栈初始化
Status Init_Stack(LinkList &S)
{
S = (LinkList)malloc(sizeof(Node));
if(!S)
return ERROR;
S->next = NULL;
return OK;
}
//功能:入栈操作
Status Push_Stack(LinkList &S,int e)
{
LinkList p = (LinkList)malloc(sizeof(Node));
if(!p)
return ERROR;
p->data = e;
p->next = S->next;
S->next = p;
return OK;
}
//功能:出栈操作
Status Pop_Stack(LinkList &S)
{
LinkList p = S->next;
if(!p)
return ERROR;
S->next = p->next;
free(p);
return OK;
}
//功能:取栈顶元素
int Top_Stack(LinkList S)
{
LinkList p = S->next;
if(!p)
return ERROR;//万一出栈的就是-1呢,所以不一定return ERROR
return p->data;
}
//功能:输出栈中所有元素
Status All_Stack(LinkList S)
{
int i = 0;
LinkList p = S->next;
if(!p)
return ERROR;
while(p)
{
printf("第%d个元素为:%d\n",++i,p->data);
p = p->next;
}
return OK;
}
//清空栈
Status Clear_Stack(LinkList &S)
{
LinkList p = S->next;
if(!p)
return ERROR;
while(p)
{
LinkList q = p;
p = p->next;
free(q);
}
//最后这一步,切记不可忘
S->next = NULL;
return OK;
}
//是否为空栈
Status qwe(LinkList &S)
{
LinkList p = S->next;
if(!p)
return 0;
else return 1;
}
//销毁栈
Status DestoryStack(LinkList &S)
{
LinkList p=S;
while(p)
{
LinkList q = p;
p = p->next;
free(q);
}
}
int main()
{
int num;
LinkList S;
int choice;
if(Init_Stack(S) ==ERROR)
exit(0);
ShowMenu();
while(1)
{
printf("Which is your choice:");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("请输入入栈元素:\n");
scanf("%d",&num);
if(Push_Stack(S,num)==OK)
printf("数据入栈成功!\n");
break;
case 2:
if(Pop_Stack(S)==ERROR)
printf("栈空,无法出栈!\n");
else
printf("出栈成功!\n");
break;
case 3:
if(Top_Stack(S)==ERROR)
printf("栈空,无法访问栈顶元素!\n");
else
printf("栈顶元素为:%d\n",Top_Stack(S));
break;
case 4:
if(All_Stack(S)==ERROR)
printf("栈空,无法输出栈中元素!\n");
else
printf("输出成功!\n");
break;
case 5:
if(Clear_Stack(S)==ERROR)
printf("栈已经为空,不用再次清空!\n");
else
printf("栈元素清空成功!\n");
break;
case 6:DestoryStack(S);break;
case 7:if(qwe(S)==0)printf("栈空!\n");
else printf("栈不为空!\n");
case 0:
printf("退出成功!\n");
exit(0);
default:printf("输入错误,请重新输入!\n");
}
}
return 0;
}