栈的底层数据结构可以是数组,也可以是链表,用链表实现栈,理论上是无限大的
下面是链栈的实现代码
#include
#include
typedef int datatype;
//Link Stack 实现顺序栈,使用链表来实现
// struct LinkList
// {
// datatype data;
// struct LinkList *next;
// };
struct stack
{
datatype data;
struct stack *next;
};
typedef struct stack Stack;
//创建栈
Stack *s;
//初始化栈
void init()
{
s=NULL;
}
//判断栈是否为空
bool Empty()
{
if(s==NULL)
{
return true;
}
else
{
return false;
}
}
//判断栈是否已满了
// void full(Stack *s)
// {
// if(s->top==realsize-1)
// {
// realsize++;
// s->data=(datatype *)realloc(s->data,realsize);
// }
// }
//入栈
void Push(datatype element)
{
Stack *p = (Stack *)malloc(sizeof(Stack));
p->data=element;
p->next=s;
s=p;
}
//出栈
void Pop()
{
if(!Empty(s))
{
s=s->next;
}
else
{
printf("栈空\n");
}
}
//取栈顶元素
datatype Top()
{
if(!Empty(s))
{
return s->data;
}
else
{
printf("栈空\n");
}
}
//销毁栈
void Destroy()
{
free(s);//因该销毁每一个元素
s=NULL;
// free(s.data); //容易导致失败
}
测试代码
#include
#include "LinkStack.h"
int main()
{
int i=0;
// struct stack s;
//初始化栈
printf("\n###########初始化栈###########\n");
init();
printf("----------------------------------");
//入栈操作
printf("\n###########入栈操作###########\n");
for(i=0;i<=10;i++)
{
Push(i);
}
printf("----------------------------------");
printf("\n###########取栈顶元素###########\n");
printf("%d\n",Top());
printf("----------------------------------");
//出栈操作
printf("\n###########出栈操作###########\n");
for(i=0;i<=12;i++)
{
Pop();
}
printf("----------------------------------");
printf("\n###########取栈顶元素###########\n");
Top();
printf("----------------------------------");
printf("\n###########销毁栈############\n");
Push(10);
Destroy();
Top();
}
这样的栈和之前数组实现的栈有共同的缺点,无法自己定义多个栈,但是全局变量避免了一个容易出错的地方,下面会说到
这里要实现和前一篇数组实现栈的自己定义多个栈,如果套用之前的方法,就会出现一个错误,数组是直接把栈作为参数传入函数,对栈的修改,就会改变原来栈的元素值。
但是这里链栈,把指针作为参数传入函数,修改参数指针指向,并不会,改变原来的指针
有两种方法可以实现,一种是将指针作为函数值返回,另一种是使用二级指针
先看第一种方法的栈的实现
#include
#include
// #define maxsize 10
typedef int datatype;
//Link Stack 实现顺序栈,使用链表来实现
// struct LinkList
// {
// datatype data;
// struct LinkList *next;
// };
struct stack
{
datatype data;
struct stack *next;
};
typedef struct stack Stack;
// Stack *s;
//初始化栈
Stack* init(Stack *s)
{
s=NULL;
return s;
}
//判断栈是否为空
bool Empty(Stack *s)
{
if(s==NULL)
{
return true;
}
else
{
return false;
}
}
//判断栈是否已满了
// void full(Stack *s)
// {
// if(s->top==realsize-1)
// {
// realsize++;
// s->data=(datatype *)realloc(s->data,realsize);
// }
// }
//入栈
Stack* Push(Stack *s,datatype element)
{
Stack *p = (Stack *)malloc(sizeof(Stack));
p->data=element;
p->next=s;
s=p; //这里指针只是副本,无法修改原来的指针,要么使用二级指针,要么返回这个指针
return s;
}
//出栈
Stack* Pop(Stack *s)
{
if(!Empty(s))
{
s=s->next;
}
else
{
printf("栈空\n");
}
return s;
}
//取栈顶元素
datatype Top(Stack *s)
{
if(!Empty(s))
{
return s->data;
}
else
{
printf("栈空\n");
}
}
//销毁栈
Stack* Destroy(Stack *s)
{
free(s);//因该销毁每一个元素
s=NULL;
return s;
// free(s.data); //容易导致失败
}
栈的测试代码
#include
#include "LinkStack1.0.h"
int main()
{
int i=0;
Stack p;
Stack *s;
s=&p;
// struct stack s;
//初始化栈
printf("\n###########初始化栈###########\n");
s=init(s);
printf("----------------------------------");
//入栈操作
printf("\n###########入栈操作###########\n");
for(i=0;i<=10;i++)
{
s=Push(s,i);
}
printf("----------------------------------");
//取栈顶元素
printf("\n###########取栈顶元素###########\n");
printf("%d\n",Top(s));
printf("----------------------------------");
//出栈操作
printf("\n###########出栈操作###########\n");
for(i=0;i<=12;i++)
{
s=Pop(s);
}
printf("----------------------------------");
//取栈顶元素
printf("\n###########取栈顶元素###########\n");
Top(s);
printf("----------------------------------");
//销毁栈
printf("\n###########销毁栈###########\n");
s=Push(s,10);
s=Destroy(s);
Top(s);
}
这种办法比较麻烦,增加了使用者的负担,增加了代码量
再看第二种方法,二级指针(指针的指针)栈的实现
#include
#include
// #define maxsize 10
typedef int datatype;
//Link Stack 实现顺序栈,使用链表来实现
struct LinkList
{
datatype data;
struct LinkList *next;
};
typedef struct stack* Stack;
//初始化栈
void init(Stack *s)
{
*s=NULL;
}
//判断栈是否为空
bool Empty(Stack *s)
{
if(*s==NULL)
{
return true;
}
else
{
return false;
}
}
//判断栈是否已满了
// void full(Stack *s)
// {
// if(s->top==realsize-1)
// {
// realsize++;
// s->data=(datatype *)realloc(s->data,realsize);
// }
// }
//入栈
void Push(Stack *s,datatype element)
{
Stack *p = (Stack *)malloc(sizeof(struct LinkList));
p->data=element;
p->next=*s;
*s=p; //这里指针只是副本,无法修改原来的指针,要么使用二级指针,要么返回这个指针
}
//出栈
void Pop(Stack *s)
{
if(!Empty(s))
{
*s=(*s)->next;
}
else
{
printf("栈空\n");
}
}
//取栈顶元素
datatype Top(Stack *s)
{
if(!Empty(s))
{
return (*s)->data;
}
else
{
printf("栈空\n");
}
}
//销毁栈
void Destroy(Stack *s)
{
free(s);//因该销毁每一个元素
*s=NULL;
// free(s.data); //容易导致失败
}
栈的测试代码
#include
#include "LinkStack2.0.h"
int main()
{
int i=0;
Stack p;
Stack *s;
s=&p;
// struct stack s;
//初始化栈
printf("\n###########初始化栈###########\n");
init(s);
printf("----------------------------------");
//入栈操作
printf("\n###########入栈操作###########\n");
for(i=0;i<=10;i++)
{
Push(s,i);
}
printf("----------------------------------");
//取栈顶元素
printf("\n###########取栈顶元素###########\n");
printf("%d\n",Top(s));
printf("----------------------------------");
//出栈操作
printf("\n###########出栈操作###########\n");
for(i=0;i<=12;i++)
{
Pop(s);
}
printf("----------------------------------");
//取栈顶元素
printf("\n###########取栈顶元素###########\n");
Top(s);
printf("----------------------------------");
//销毁栈
printf("\n###########销毁栈###########\n");
Push(s,10);
Destroy(s);
Top(s);
}