引言:在上次复习了线性表的基本操作后,现在我们将目光转移到下一数据结构中来。至此,正式开始数据结构——栈的学习
一.栈的定义
定义:栈是仅在一端进行插入和删除的线性表
二.栈的表达方式
同线性表一样,栈的表达方式也分为顺序与链式两种
1.顺序表达
原理同顺序表的基本相同,但是要注意栈是遵循先进后出的原理。
理解栈的进出原理,现在我们可以看代码:
struct stack//定义结构体
{
int data[Max];//数据域
int top;//指针指向栈顶
};
同理,以上的是最基本的实现,其他操作要看需求。
2.顺序表达的插入与输出
这里的重点是根据栈顶的指针来判断,所以理解栈顶指针就很重要
顺序插入
void push(struct stack *p,int k)//顺序插入
{
int i,j;
if(p->top==Max-1)//如果栈顶指针满的话,就判为栈为满,无法在插入
exit(0);
for(i=0;i<k;i++)
{
cin>>p->data[i];
p->top++;//每一次输入数据后,指针都要加一
}
}
顺序输出
void pop(struct stack *q)//输出
{
int i,j;
if(q->top==-1)//如果指针为-1,说明栈为空,无法在输出
exit(0);
for(i=q->top-1;i>=0;i--)
{
cout<<q->data[i]<<" ";
q->top--;//每一次输出数据后,指针都要减一
}
}
现在我们就可以写出完整表达式:
#include <iostream>
using namespace std;
#define Max 103
struct stack//定义
{
int data[Max];
int top;
};
void push(struct stack *p,int k)//插入
{
int i,j;
if(p->top==Max-1)
exit(0);
for(i=0;i<k;i++)
{
cin>>p->data[i];
p->top++;
}
}
void pop(struct stack *q)//输出
{
int i,j;
if(q->top==-1)
exit(0);
for(i=q->top-1;i>=0;i--)
{
cout<<q->data[i]<<" ";
q->top--;
}
}
int main()
{
int n,m,j,k,l,i;
struct stack list;
list.top=0;
cin>>n;
push(&list,n);
pop(&list);
return 0;
}
3.共享栈
我们都知道,栈是一种只在一端进行操作的数据结构。但如果我们将两个栈进行对合,就得到了共享栈。
共享栈的定义
struct stack
{
int data[Max];
int top1;//指向栈底
int top2;//指向栈顶
};
共享栈的插入
void push(struct stack *p,int k,int judge_sum)
{
if(p->top1+1==p->top2)//进行栈是否为满的判断
exit(0);
if(judge_sum==1)//下栈区进行操作
{
for(int i=0;i<k;i++)
{
cin>>p->data[i];
p->top1++;
}
}
if(judge_sum==2)//上栈区进行操作
{
for(int j=p->top2;j>=(Max-k);j--)
{
cin>>p->data[j];
p->top2--;
}
}
}
共享栈的输出
同共享栈的输入一样,共享栈输出并不复杂,只是操作循序上有些不同
void pop(struct stack *q,int judge_sum)
{
if(judge_sum==1)
{
if(q->top1==-1)
exit(0);
else
for(int i=q->top1-1;i>=0;i--)
{
cout<<q->data[i]<<" ";
q->top1--;
}
}
if(judge_sum==2)
{
if(q->top2==Max)
exit(0);
else
for(int j=q->top2+1;j<Max;j++)
{
cout<<q->data[j]<<" ";
q->top2++;
}
}
}
现在我们就可以写出共享栈的完整代码了
#include <iostream>
using namespace std;
#define Max 103
struct stack
{
int data[Max];
int top1;
int top2;
};
void push(struct stack *p,int k,int judge_sum)//插入
{
if(p->top1+1==p->top2)
exit(0);
if(judge_sum==1)
{
for(int i=0;i<k;i++)
{
cin>>p->data[i];
p->top1++;
}
}
if(judge_sum==2)
{
for(int j=p->top2;j>=(Max-k);j--)
{
cin>>p->data[j];
p->top2--;
}
}
}
void pop(struct stack *q,int judge_sum)//输出
{
if(judge_sum==1)
{
if(q->top1==-1)
exit(0);
else
for(int i=q->top1-1;i>=0;i--)
{
cout<<q->data[i]<<" ";
q->top1--;
}
}
if(judge_sum==2)
{
if(q->top2==Max)
exit(0);
else
for(int j=q->top2+1;j<Max;j++)
{
cout<<q->data[j]<<" ";
q->top2++;
}
}
}
int main()
{
int n,m,j,k,l,i;
struct stack list;
list.top1=0;
list.top2=Max-1;
cin>>n>>m;
push(&list,n,m);
pop(&list,m);
return 0;
}
4.链式栈
终于到了链式栈,在链式操作中,我们最熟悉的就是链表,现在我们实现链式栈,其中的大部分东西与链式顺序表一样。
链式表达
struct stack //定义链式表达栈
{
int data;
struct stack *next;//指向下一节点,这里同链表思想是一样的
};
struct links //这里我们定义栈指针,也就是top指针,因为top指针只有一个,
//所以我们定义一个
{
struct stack *top;
int count;
};
链式插入
链式插入并不复杂,其原理像极了链表的头插法
void push(struct links *p,int k)
{
int i,j;
for(i=0;i<k;i++)
{
struct stack *s = new(struct stack);//申请我们定义的栈节点
cin>>s->data;
s->next=p->top;//这里就是头插法的类似操作
p->top=s;
p->count++;
}
}
链式输出
通过输入,我们得知链式栈的输入像极了头插法,所以链式输出与链表的输出类似
void pop(struct links *q)
{
struct stack *s;
if(q->top==NULL)//判断链式栈是否为空
exit(0);
while(q->count!=0)
{
cout<<q->top->data<<" ";
s=q->top;
q->top=q->top->next;
delete(s);
q->count--;
}
}
完整操作
#include <iostream>
using namespace std;
struct stack
{
int data;
struct stack *next;
};
struct links
{
struct stack *top;
int count;
};
void push(struct links *p,int k)
{
int i,j;
for(i=0;i<k;i++)
{
struct stack *s = new(struct stack);
cin>>s->data;
s->next=p->top;
p->top=s;
p->count++;
}
}
void pop(struct links *q)
{
struct stack *s;
if(q->top==NULL)
exit(0);
while(q->count!=0)
{
cout<<q->top->data<<" ";
s=q->top;
q->top=q->top->next;
delete(s);
q->count--;
}
}
int main()
{
int n,m,j,k,l,i;
struct links link;
link.top=NULL;
link.count=0;
cin>>n;
push(&link,n);
pop(&link);
return 0;
}
后记:
栈的基本操作到这里就差不多的,希望对各位有所帮助,在后面,我们将会继续学习接下来的数据结构与算法,请期待。