#include
#include
#define OK 1
#define ERROR 0
typedef int Status;
typedef struct stackNode{
long int data;
struct stackNode* next;
}STACKNODE;//定义链栈结点结构
typedef struct stackNode* nodePointer;
typedef struct linkStack{
nodePointer top;
int counter;
}LINKSTACK;//定义指针top和计数器结构
int printMenu(void);
void PleaseInit(void);
Status initLinkStack(LINKSTACK* T);
Status insertLinkStack(LINKSTACK* T);
Status printElementNumber(LINKSTACK* T);
Status linkStackEmpty(const LINKSTACK* T);
Status returnLinkStackTop(const LINKSTACK* T);
Status pop(LINKSTACK* T);
Status clearLinkStack(LINKSTACK* T);
Status destroyLinkStack(LINKSTACK* T);
int main(int argc, char *argv[]) {
int menuChoice;
LINKSTACK topLinkStack;//声明一个LINKSTACK类型的变量,以后用以指向链栈结点
topLinkStack.top=NULL;//初始化为NULL,表示没有指向链栈可见当前链栈为空
while(menuChoice=printMenu())
{
switch(menuChoice)
{
case 1:
initLinkStack(&topLinkStack);
break;
case 2:
destroyLinkStack(&topLinkStack);
break;
case 3:
clearLinkStack(&topLinkStack);
break;
case 4:
linkStackEmpty(&topLinkStack);
break;
case 5:
returnLinkStackTop(&topLinkStack);
break;
case 6:
insertLinkStack(&topLinkStack);
break;
case 7:
pop(&topLinkStack);
break;
case 8:
printElementNumber(&topLinkStack);
break;
}
}
return 0;
}
//打印菜单
int printMenu(void)
{
int choice;
printf("****************链栈练习******************\n");
printf("1:初始化链栈\n");
printf("2:销毁链栈\n");
printf("3:清空链栈\n");
printf("4:链栈是否为空\n");
printf("5:返回栈顶元素\n");
printf("6:元素压入到链栈中\n");
printf("7:删除栈顶元素,并返回\n");
printf("8:当前栈元素个数\n");
printf("按下0退出程序\n");
printf("*******************************************\n");
printf("请选择:");
scanf("%d",&choice);
return choice;
}
//1:初始化链栈
Status initLinkStack(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--1:初始化链栈--\n");
if(T->top!=NULL)
{
printf("请勿重复操作\n");
return ERROR;
}
T->top=(nodePointer)malloc(sizeof(STACKNODE));
if(T->top==NULL)
{
printf("初始化失败!\n");
return ERROR;
}
T->counter=0;//初始化为0,表示链栈为空。但是已经初始化了
T->top->next=NULL;//申请分配一个空间之后,它是第一个元素所以要压入栈。栈底元素没有指向别的结点
printf("初始化成功!\n");
return OK;
}
//2:销毁链栈
Status destroyLinkStack(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--2:销毁链栈--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
char inputValue;
printf("是否要销毁链表?(Y/N)");
scanf(" %c",&inputValue);
fflush(stdin);
if(inputValue=='Y'||inputValue=='y')
{
nodePointer param;
while(T->top->next!=NULL)
{
param=T->top;
T->top=param->next;//回退
T->counter--;
free(param);//把结点回收
}
free(T->top);
T->top=NULL;
printf("销毁成功!\n");
return OK;
}
if(inputValue=='N'||inputValue=='n')
{
return OK;
}
return OK;
}
//3:清空链栈
Status clearLinkStack(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--3:清空链栈--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
if(T->counter==0)
{
printf("当前栈为空,请先压入元素吧\n");
return ERROR;
}
char inputValue;
printf("是否要清空链表?(Y/N)");
scanf(" %c",&inputValue);
fflush(stdin);
if(inputValue=='Y'||inputValue=='y')
{
nodePointer param;
while(T->top->next!=NULL)
{
param=T->top;
T->top=param->next;//回退
T->counter--;
free(param);//把结点回收
}
printf("清除成功!\n");
return OK;
}
if(inputValue=='N'||inputValue=='n')
{
return OK;
}
return OK;
}
//4:链栈是否为空
Status linkStackEmpty(const LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--4:链栈是否为空--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
if(T->counter==0)
{
printf("当前栈为空,请先压入元素吧\n");
return ERROR;
}
printf("当前链栈不为空\n");
return OK;
}
//5:返回栈顶元素
Status returnLinkStackTop(const LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--5:返回栈顶元素--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
if(T->counter==0)
{
printf("当前栈为空,请先压入元素吧\n");
return ERROR;
}
printf("当前栈顶元素为:%d\n",T->top->next->data);
return OK;
}
//6:元素压入到链栈中
Status insertLinkStack(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--6:元素压入到链栈中--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
nodePointer param;
int pushElement;
param=T->top;
printf("请输入要压入的元素:");
scanf("%d",&pushElement);
fflush(stdin);//防止多输入
param=(nodePointer)malloc(sizeof(STACKNODE));
if(param==NULL)
{
printf("压入失败!\n");
return ERROR;
}
T->top->data=pushElement;
param->next=T->top;
T->counter++;
T->top=param;
printf("压入成功!\n");
return OK;
}
//7:删除栈顶元素,并返回
Status pop(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--7:删除栈顶元素,并返回--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
if(T->counter==0)
{
printf("当前栈为空,请先压入元素吧\n");
return ERROR;
}
nodePointer param;
param=T->top;
printf("当前栈顶元素为:%d\n",T->top->next->data);
if(param->next!=NULL)
{
T->top=param->next;//回退
T->counter--;
free(param);//把结点回收
printf("删除成功!\n");
}
return OK;
}
//8:当前栈元素个数
Status printElementNumber(LINKSTACK* T)
{
system("cls");//清屏
printf("当前选的为--8:当前栈元素个数--\n");
if(T->top==NULL)
{
PleaseInit();
return ERROR;
}
if(T->counter==0)
{
printf("当前栈为空,请先压入元素吧\n");
return ERROR;
}
printf("当前栈元素个数为:%d\n",T->counter);
return OK;
}
//请先初始化样式
void PleaseInit(void)
{
printf("**************\n");
printf("*请先初始化 *\n");
printf("**************\n\n");
}
(一)、
typedef struct stackNode{
long int data;
struct stackNode* next;
}STACKNODE;//定义链栈结点结构
typedef struct stackNode* nodePointer;
typedef struct linkStack{
nodePointer top;
int counter;
}LINKSTACK;//定义指针top和计数器结构
第一个结构是定义了一个结点结构,就像链表一样的结点。效果如下图
第二个是定义了指向结点的结构,里面包含一个指向栈结点的指针和一个计数器。效果图如下
T->top=(nodePointer)malloc(sizeof(STACKNODE));
T->counter=0;//初始化为0,表示链栈为空。但是已经初始化了
T->top->next=NULL;//申请分配一个空间之后,它是第一个元素所以要压入栈。栈底元素没有指向别的结点
上面三条语句,第一个是动态分配栈结点空间并且top指向它,然后counter=0,这个分配的地址空间用于存储栈底元素。效果图如下
这个初始化和下面的链栈效果是一样的,当top=0时为空栈
(三)、压入栈函数中
param=(nodePointer)malloc(sizeof(STACKNODE));
T->top->data=pushElement;
param->next=T->top;
T->counter++;
T->top=param;
下面我们用一组图片说明上面的5条语句的意思
param=(nodePointer)malloc(sizeof(STACKNODE));
动态分配空间,返回param指针指向这个地址,注意指针类型它和T不一样。
T->top->data=pushElement;
接着就是把输入的值放入第一个地址空间中,这里用data代替(我不会说是因为太难画了才代替的 ̄へ ̄)。
param->next=T->top;
T->counter++;
T->top=param;
最后一句就是T指针向前移动,指向新分配的空间。以后的压栈就是上面的重复操作。
(四)、出栈,以销毁链栈操作为例
while(T->top->next!=NULL)
{
param=T->top;
T->top=param->next;//回退
T->counter--;
free(param);//把结点回收
}
free(T->top);
T->top=NULL;
咱们接着看几幅图理解一下如何出栈并销毁链栈的。
假设栈中的元素如下
现在开始销毁栈
param=T->top;
T->top=param->next
这一步T回退到之前(能不能回退到上一个地址,需要while中的T->top->next!=NULL判断,它的意思是,如果不是栈底的话就可以回退,否则退出循环)
T->counter–;
free(param)
因为T已经回退了,所以之前的结点就可以销毁了。
就这样循环下去,直到循环条件不成立。退出循环,到下面的情况
free(T->top);
最后
T->top=NULL;
①:初始化栈,然后压出1 2 3 4 5元素到栈中。并返回栈顶元素
②:返回并删除栈顶元素,判断是否为空栈,最后清空栈
③:看是否能返回栈顶元素,最后销毁栈
如有错误欢迎指出
本篇博客源代码和文件已经上传,欢迎下载
https://download.csdn.net/download/qq_42683219/12882019