栈与队列
- 一.栈(stack)
- A.前知(定义+基本操作)
- B.栈的顺序存储----------图片
- =======================================
- +++++++++++++顺序栈的两种实现+++++++++++++
- =======================================
- 1. top=-1情况:
- a1.定义typedef struct
- a2.初始化操作Initstack(sqstack &s)
- a3.是否栈空stackempty(sqstack s)
- a4.是否栈满stackfull(sqstack s)
- a5.进栈操作push(sqstack &s,elemtype x)
- a6.出栈操作pop(sqstack &s,elemtype &x)
- a7.读取栈顶元素Gettop(sqstack s,elemtype &x)
- =======================================
- 2. top=0的情况:
- b1.定义typedef struct
- b2.初始化操作Initstack(sqstack &s)
- b3.是否栈空stackempty(sqstack s)
- b4.是否栈满 stackfull(sqstack s)
- b5.进栈操作push(sqstack &s,elemtype x)
- b6.出栈操作pop(sqstack &s,elemtype &x)
- b7.读取栈顶元素Gettop(sqstack s,elemtype &x)
- =======================================
- +++++++++++共享栈(顺序栈的一种)++++++++++
- =======================================
- c1.定义
- c2.初始化
- c3.是否栈满
- =======================================
- C.栈的链式存储--------图片(与单链表类似)
- 二.队列
- A.前知(定义+基本操作)
- B.队列的顺序存储-------图片
- 1.定义typedef struct
- 2.初始化
- 3.队列是否空
- 4.入队(因为涉及判满------从这里开始逐步循环队列化)
- ++++++++++++++++++循环队列++++++++++++++
- =======================================
- D1.循环队列--------关键代码%
- D2.循环队列 --------是否空queueempty(sqqueue s)
- D3.循环队列---------入队Enqueue(sqqueue &q,elemtype x)
- D4.循环队列--------出队Dequeue(sqqueue &q,elemtype &x)
- D5.循环队列--------读取队头元素
- D6.循环队列--------判断循环队列满/空
- D7.循环队列----------rear的不同指向
- =======================================
- C.队列的链式存储-------图片
- D.双端队列(一般考察序列合法性)
- 三.应用
一.栈(stack)
A.前知(定义+基本操作)
(后进先出=last in first out=LIFO)
创,销
1.Initstack(&S)
2.Destroystack(&S)
增,删
3.Push(&S,x)
4.pop(&S,&x)
查
5.Gettop(S,&x)
是否空
6.Stackempty(S)
B.栈的顺序存储----------图片
=======================================
+++++++++++++顺序栈的两种实现+++++++++++++
=======================================
1. top=-1情况:
a1.定义typedef struct
#define maxsize 10
typedef struct
{
elemtype data[maxsize];//静态数组存放元素
int top; //栈顶指针
} sqstack;//sequence顺序
int main()
{
sqstack s;//用声明顺序栈(分配空间)
}
a2.初始化操作Initstack(sqstack &s)
void Initstack(sqstack &s)
{
s.top =-1;
}
a3.是否栈空stackempty(sqstack s)
bool stackempty(sqstack s)
{
if(s.top ==-1)return true;//空
else return false;//不空
}
a4.是否栈满stackfull(sqstack s)
bool stackfull(sqstack s)
{
if(s.top ==maxsize-1)return true;//栈满
else return false;//栈不满
}
a5.进栈操作push(sqstack &s,elemtype x)
bool push(sqstack &s,elemtype x)
{
if(s.top ==maxsize-1)return false;//栈满
s.top =s.top +1;//指针先加1
s.data [s.top ]=x;//新元素入栈
//等价于s.data[++s.top]=x
return true;
}
a6.出栈操作pop(sqstack &s,elemtype &x)
bool pop(sqstack &s,elemtype &x)
{
if(s.top=-1)return false;//栈空
x=s.data [s.top ]//栈顶元素先出栈
s.top =s.top -1;//数据还存留在内存,只是逻辑上删除
//等价于x=s.data [s.top--]
return true;
}
a7.读取栈顶元素Gettop(sqstack s,elemtype &x)
bool Gettop(sqstack s,elemtype &x)
{
if(s.top ==-1)return false;//栈空
x=s.data [s.top ];//栈顶元素
return true;
}
=======================================
2. top=0的情况:
b1.定义typedef struct
#define maxsize 10
typedef struct
{
elemtype data[maxsize];//静态数组存放元素
int top; //栈顶指针
} sqstack;//sequence顺序
int main()
{
sqstack s;//用声明顺序栈(分配空间)
}
b2.初始化操作Initstack(sqstack &s)
void Initstack(sqstack &s)
{
s.top =0;
}
b3.是否栈空stackempty(sqstack s)
bool stackempty(sqstack s)
{
if(s.top ==0)return true;//空
else return false;//不空
}
b4.是否栈满 stackfull(sqstack s)
bool stackfull(sqstack s)
{
if(s.top ==maxsize)return true;//栈满
else return false;//栈不满
}
b5.进栈操作push(sqstack &s,elemtype x)
bool push(sqstack &s,elemtype x)
{
if(s.top ==maxsize)return false;//栈满
s.data [s.top ]=x;//新元素入栈
s.top =s.top +1;//指针加1
//等价于s.data[s.top++]=x
return true;
}
b6.出栈操作pop(sqstack &s,elemtype &x)
bool pop(sqstack &s,elemtype &x)
{
if(s.top=0)return false;//栈空
s.top =s.top -1;//数据还存留在内存,只是逻辑上删除
x=s.data [s.top ]//栈顶元素出栈
//等价于x=s.data [--s.top]
return true;
}
b7.读取栈顶元素Gettop(sqstack s,elemtype &x)
bool Gettop(sqstack s,elemtype &x)
{
if(s.top ==0)return false;//栈空
x=s.data [s.top -1];//栈顶元素
return true;
}
=======================================
+++++++++++共享栈(顺序栈的一种)++++++++++
=======================================
c1.定义
#define maxsize 10
typedef struct
{
elemtype data[maxsize];//静态数组存放元素
int top0; //0号栈栈顶指针
int top1; //1号栈栈顶指针
} shstack; //share
int main()
{
shstack s;//用声明顺序栈(分配空间)
}
c2.初始化
void Initstack(sqstack &s)
{
//初始栈顶指针
s.top0 = -1;
s.top1 = maxszie;
}
c3.是否栈满
bool stackfull(shstack s)
{
if(s.top0+1=s.top1)return true;//栈满
else return false;//栈不满
}
=======================================
C.栈的链式存储--------图片(与单链表类似)
1.定义
typedef struct Linknode
{
elemtype data;
struct Linknode* next;
}*Listack;
2.其他请自行实现
二.队列
A.前知(定义+基本操作)
先进先出=first in first out=FIFO
创,销
1.Iniqueue(&S)
2.Destroyqueue(&S)
增,删
3.Enqueue(&S,x)入队
4.Dequeue(&S,&x)出队
查
5.Gethead(S,&x)访问队头
是否空
6.Stackempty(S)
B.队列的顺序存储-------图片
1.定义typedef struct
#define maxsize 10
typedef struct
{
elemtype data[maxsize];
int front,rear;
}sqqueue;
int main()
{
sqqueue q;
}
2.初始化
//初始化
void Initqueue(sqqueue &q)
{
//队头,队尾指针指向0
q.front =q.rear =0;
}
3.队列是否空
bool queueempty(sqqueue s)
{
if(q.front==q.rear) return true;//空
else return false;//不空
}
4.入队(因为涉及判满------从这里开始逐步循环队列化)
如何判断队列已满呢
此处让if(rear==maxsize)判断的话是错误的,如下图这种情况:
//入队
bool Enqueue(sqqueue &q,elemtype x)
{
if(队列已满)return false;// 队列满,报错
q.data [q.rear ]=x;//x插入队尾
q.rear =q.rear +1;//队尾指针向后移动
return true;
}
那么如何判断是否满呢?
如上图中:data[0] data[1] data[2]未满
那就使q.rear =(q.rear +1)%maxsize
此时rear=(9+1)%10=0 ,那么此时的队列变为循环队列
//入队
bool Enqueue(sqqueue &q,elemtype x)
{
if(队列已满)return false;// 队列满,报错
q.data [q.rear ]=x;//x插入队尾
q.rear =(q.rear +1)%maxsize;//(加1)%10
return true;
}
++++++++++++++++++循环队列++++++++++++++
=======================================
D1.循环队列--------关键代码%
q.data [q.rear ]=x;//x插入队尾
q.rear =(q.rear +1)%maxsize;//(加1)%10
D2.循环队列 --------是否空queueempty(sqqueue s)
bool queueempty(sqqueue q)
{
if(q.front==q.rear) return true;//空
else return false;//不空
}
D3.循环队列---------入队Enqueue(sqqueue &q,elemtype x)
//入队
bool Enqueue(sqqueue &q,elemtype x)
{
if((q.rear + 1)%maxsize==q.front )return false;// 队列满,报错
q.data [q.rear ]=x;//x插入队尾
q.rear =(q.rear + 1)%maxsize//队尾指针向后移动
return true;
}
D4.循环队列--------出队Dequeue(sqqueue &q,elemtype &x)
//出队
bool Dequeue(sqqueue &q,elemtype &x)
{
if(q.front ==q.rear )return false;//队空报错
x=q.data [q.front ];//引用x赋值返回
q.front =(q.front +1)%maxsize;//指针后移
return true;
}
D5.循环队列--------读取队头元素
bool Gethead(sqqueue q,elemtype &x)
{
if(q.front ==q.rear )return false;//队空报错
x=q.data [q.front ];
return true;
}
D6.循环队列--------判断循环队列满/空
此时判断错误
空:q.front==q.rear
满:q.front==q.rear
那么如何判断呢?如下三个方法
方法一.浪费一个空间
初始化:front=rear=0
满:(q.rear + 1)%maxsize==q.front
空:q.front ==q.rear
队列元素个数:(rear+maxsize-front)%maxsize
方法二.不浪费,定义size
初始化:front=rear=0,size=0
插入成功:size++
删除成功:size--
满:size=maxsize
空:size=0
方法三.不浪费,定义tag
初始化:front=rear=0,tag=0
每次删除成功:tag=0
每次插入成功:tag=1
满:front==rear&&tag==1
空:front==rear&&tag==0
D7.循环队列----------rear的不同指向
1.rear=0(rear指向队尾元素的后一个位置)
a.初始化
//初始化
void Initqueue(sqqueue &q)
{
//队头,队尾指针指向0
q.front =q.rear =0;
}
b.入队-----关键code
q.data [q.rear ]=x;//x插入队尾
q.rear =(q.rear + 1)%maxsize//队尾指针向后移动
c.出队操作相同-----关键code
x=q.data [q.front ];//引用x赋值返回
q.front =(q.front +1)%maxsize;//指针后移
d.判空-----关键code
浪费一个空间的判空,判满
空:q.front==q.rear
满:(q.rear + 1)%maxsize==q.front
2.rear=maxsize-1(rear指向队尾元素)
a.初始化
//初始化
void Initqueue(sqqueue &q)
{
//队头,队尾指针指向0
q.front = 0;
q.rear = maxsize-1;
}
b.入队-----关键code
q.rear =(q.rear + 1)%maxsize//队尾指针先向后移动
q.data [q.rear ]=x;//x插入队尾
c.出队操作相同-----关键code
x=q.data [q.front ];//引用x赋值返回
q.front =(q.front +1)%maxsize;//指针后移
d.判空、判满-----思路+关键code+思路
此时无法判断
空:(q.rear + 1)%maxsize==q.front
满:(q.rear + 1)%maxsize==q.front
换思路:
1.浪费一个空间
空:(q.rear + 1)%maxsize==q.front
满:(q.rear + 2)%maxsize==q.front
2.定义size
空:size=0
满:size =maxsize
3.定义tag
空:(q.rear + 1)%maxsize==q.front&&tag=0(删除)
满:(q.rear + 1)%maxsize==q.front&&tag=1(插入)
=======================================
C.队列的链式存储-------图片
1.定义typedef struct
typedef struct Linknode
{
elemtype data;
struct Linknode *next;
} Linknode;
typedef struct
{
Linknode *front,*rear;//队头,队尾
}Linkqueue;
2.初始化----带头结点
//初始化
void Initqueue(Linkqueue &q)
{
q.front =q.rear =(Linknode*) malloc(sizeof(Linknode));
q.front ->NULL;
}
3.初始化----不带头结点
//初始化
void Initqueue(Linkqueue &q)
{
q.front = NULL
q.rear = NULL;
}
4.判空----带头结点
bool Isempty(Linkqueue &q)
{
//或者q.front->next=NULL
if(q.front == q.rear )return true;
else return true;
}
5.判空----不带头结点
bool Isempty(Linkqueue &q)
{
//或者q.rear=NULL
if(q.front == NULL)return true;
else return true;
}
6.入队----带头结点
//入队
void Enqueue(Linkqueue &q,elemtype x)
{
Linknode * s=(Linknode *)malloc(sizeof(Linknode));
s->data=x;
s->next==NULL;
q.rear ->next=s;//新节点插入到rear之后
q.rear =s;//修改表尾指针
}
7.入队----不带头结点
//入队
void Enqueue(Linkqueue &q,elemtype x)
{
Linknode *s=(Linknode *)malloc(sizeof(Linknode));
s->data =x;
s->next =NULL;
//不带头结点,第一个元素特殊处理
if(q.front ==NULL)//空队列中插入第一个元素
{
//修改队头,队尾指针
q.front =s;
q.rear =s;
}
else
{
q.rear ->next=s;//新节点插入rear之后
q.rear =s;//修改rear指针
}
}
8.出队----带头结点
//出队
bool Dequeue(Linkqueue &q,elemtype &x)
{
if(q.front ==q.rear )return false;//空队
Linknode * p=q.front ->next;
x=p->data; //返回x
q.front ->next=p->next;//修改头结点的next指针
if(q.rear ==p) q.rear =q.front ;//最后一个结点出队,修改rear指针
free(p);
return true;
}
9.出队----不带头结点
//出队
bool Dequeue(Linkqueue &q,elemtyoe &x)
{
if(q.front == NULL)return false;//空队
Linknode *p=q.front;//P指向此次出队的结点
x=p->data;//返回x
q.front =p->next;//修改front指针
if(q.rear ==p)//此次是最后一个结点出队
{
q.front =NULL;//front,rear指向NULL
q.rear =NULL;
}
free(p);
return true;
}
10.判满----顺序存储/链式存储
顺序存储:预分配的空间耗尽则满
链式存储:一般不队满,除非没内存
D.双端队列(一般考察序列合法性)