C语言字符型链栈,数据结构(C语言版)——链栈(代码版)

数据结构(C语言版)——链栈(代码版)

数据结构(C语言版)——链栈(代码版)

#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和计数器结构

第一个结构是定义了一个结点结构,就像链表一样的结点。效果如下图

cc112965b91df56d8e5bdd397c6df884.png

第二个是定义了指向结点的结构,里面包含一个指向栈结点的指针和一个计数器。效果图如下

b5566f446592cbc5fcb24a19d13c3495.png

(二)、初始化函数中

T->top=(nodePointer)malloc(sizeof(STACKNODE));

T->counter=0;//初始化为0,表示链栈为空。但是已经初始化了

T->top->next=NULL;//申请分配一个空间之后,它是第一个元素所以要压入栈。栈底元素没有指向别的结点

上面三条语句,第一个是动态分配栈结点空间并且top指向它,然后counter=0,这个分配的地址空间用于存储栈底元素。效果图如下

a7bd9e7e3490dd3548e4fcd0170ef3cc.png

这个初始化和下面的链栈效果是一样的,当top=0时为空栈

caa71f823a862cd0a2fd446bbd295f19.png

(三)、压入栈函数中

param=(nodePointer)malloc(sizeof(STACKNODE));

T->top->data=pushElement;

param->next=T->top;

T->counter++;

T->top=param;

下面我们用一组图片说明上面的5条语句的意思

param=(nodePointer)malloc(sizeof(STACKNODE));

7938b4d845de590205fa389970de0e32.png

动态分配空间,返回param指针指向这个地址,注意指针类型它和T不一样。

T->top->data=pushElement;

d3a45a6ec41b559f259d97399ef8d4ec.png

接着就是把输入的值放入第一个地址空间中,这里用data代替(我不会说是因为太难画了才代替的 ̄へ ̄)。

param->next=T->top;

0ce81f73342338f955f1e5091cb924d7.png

使新分配的地址空间中的指针指向了之前的值。

T->counter++;

0a0edcac87ffec866f74e75473ec1832.png

counter+1

T->top=param;

20332e4031dcfaf63edc234e381403f2.png

最后一句就是T指针向前移动,指向新分配的空间。以后的压栈就是上面的重复操作。

(四)、出栈,以销毁链栈操作为例

while(T->top->next!=NULL)

{

param=T->top;

T->top=param->next;//回退

T->counter--;

free(param);//把结点回收

}

free(T->top);

T->top=NULL;

咱们接着看几幅图理解一下如何出栈并销毁链栈的。

假设栈中的元素如下

ad410ade3e3c76e5138a7d3420729d5f.png

现在开始销毁栈

param=T->top;

4ff82af4730bf1e1adc91df43a6087b2.png

parm和T->top指向同一个地方

T->top=param->next

60c7b0a8fba0ae70c0eda00938073cc8.png

这一步T回退到之前(能不能回退到上一个地址,需要while中的T->top->next!=NULL判断,它的意思是,如果不是栈底的话就可以回退,否则退出循环)

T->counter–;

3d34eb4a93e3dcfdc5207187dc217e25.png

把counter-1;表示出栈

free(param)

4b7041d5cb2c8c651cd6dce350140e4b.png

因为T已经回退了,所以之前的结点就可以销毁了。

就这样循环下去,直到循环条件不成立。退出循环,到下面的情况

47bbbac4f7dfa219cf8112d1f4dca881.png

free(T->top);

de75c0ab46f8c1de71375165f5905f9d.png

把T->top指向的地址空间给销毁了。

最后

T->top=NULL;

0fd71a276f099efb88bcefe846ff4176.png

top指向了空,以上是销毁的全部过程

①:初始化栈,然后压出1 2 3 4 5元素到栈中。并返回栈顶元素

85aa3e1cc036c450a2e626bb23d3947b.png

c1d3d9e8fa5e6302af48a776bdb8d2b3.png

90786f5d5aa09becdb66685526c9a2e3.png

②:返回并删除栈顶元素,判断是否为空栈,最后清空栈

de55e110d4b4369e7aaca9b40eedb12a.png

37934d31c0b46c816708c09ab2d578a1.png

244a7db6c9bb568f03bc4ea241766e16.png

③:看是否能返回栈顶元素,最后销毁栈

e09f91bf875bf2c03668f1db6946de52.png

9d64e6ac22c6ba20cb71f2dfcecc381b.png

如有错误欢迎指出

本篇博客源代码和文件已经上传,欢迎下载

https://download.csdn.net/download/qq_42683219/12882019

数据结构(C语言版)——链栈(代码版)相关教程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值