堆栈也可以采用链式存储结构,称为链栈。链栈常采用单链表表示。其实现是将链表的表头作为栈顶实现,这样就不需要在单链表中增加头结点,栈顶指针就是链表的头指针。
下面的代码实现了链栈的相关操作,其中有个错误关于重复申请堆空间让我郁闷了会儿,不过后来找出来了。
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
char data;
struct node *next;
}linkstack;
linkstack * Linkstack_Create(); //创建链栈
char Linkstack_GetTop(linkstack *q); //取得栈顶
linkstack *Linkstack_In(linkstack *q, char dat); //入栈
linkstack * Linkstack_Out(linkstack *q, char *dat); //出栈
void Linkstack_SetNull(linkstack *q); //置空栈
int Linkstack_Empty(linkstack *q); //栈是否为空
void ShowLinkstack(linkstack *q); //输出显示栈
int main(void)
{
linkstack *q;
int choice, ans;
char dat;
printf("链栈的操作练习:\n");
printf("请依次输入链栈字符数据('#'号表示结束):\n");
q = Linkstack_Create();
getchar();
while(1)
{
printf("链栈操作:\n");
printf("1.取得栈顶结点\n");
printf("2.入栈\n");
printf("3.出栈\n");
printf("4.输出显示链栈\n");
printf("5.退出程序\n");
printf("做出选择:");
scanf("%d", &choice);
getchar(); //消除回车为后面带来的影响
switch(choice)
{
case 1:
dat = Linkstack_GetTop(q);
if(dat == '\0')
printf("取得头结点失败!\n");
else
printf("头结点为%c\n", dat);
break;
case 2:
printf("输入想入栈的字符:\n");
dat = getchar();
q = Linkstack_In(q, dat);
break;
case 3:
q = Linkstack_Out(q, &dat);
if(dat != '\0')
printf("出栈的字符为%c\n", dat);
break;
case 4:
printf("输出的字符依次为:\n");
ShowLinkstack(q);
break;
case 5:
return 0;
break;
default:
printf("选择无效!\n");
break;
}
}
return 1;
}
//链栈置空
void Linkstack_SetNull(linkstack *q)
{
linkstack *s;
while(q != NULL) //链栈置空时需要释放每个结点的空间
{
s = q;
q = q->next;
free(s);
}
}
//判断链栈是否为空
int Linkstack_Empty(linkstack *q)
{
if(q == NULL)
return 1;
else
return 0;
}
//创建链栈
linkstack * Linkstack_Create()
{
linkstack *q = NULL;
char ch;
Linkstack_SetNull(q);
ch = getchar();
while(ch != '#')
{
// q = (linkstack*)malloc(sizeof(linkstack));
//此句又让人纠结了好久,有此句时创建的链栈只有栈顶字符,申请了两次空间(下面入栈函数中一次),至于为什么会造成这种结果,暂时不知道- -!!
q = Linkstack_In(q, ch);
ch = getchar();
}
return q;
}
//取得栈顶结点
char Linkstack_GetTop(linkstack *q)
{
if(Linkstack_Empty(q)) //先要判断栈顶是否为空
return '\0';
else
return q->data;
}
//入栈,返回栈顶结点指针
linkstack *Linkstack_In(linkstack *q, char dat)
{
linkstack *e;
e = (linkstack*)malloc(sizeof(linkstack));
e->data = dat;
e->next = q;
return e;
}
//出栈,返回栈顶结点指针
linkstack *Linkstack_Out(linkstack *q, char *dat)
{
linkstack *s;
if(Linkstack_Empty(q)) //先要判断栈顶是否为空
{
*dat = '\0';
return NULL;
}
else
{
*dat = q->data;
s = q;
q = q->next;
free(s);
return q;
}
}
//输出显示链栈,从栈顶到栈底
void ShowLinkstack(linkstack *q)
{
linkstack *s;
s = q;
while(s != NULL)
{
putchar(s->data);
putchar(' ');
s = s->next;
}
printf("\n");
}