堆栈
存储结构
用顺序栈和链栈都可以,但用顺序栈更常见
图像
top指向的是真正的栈顶元素之上的位置
C |
B |
A |
表示
堆栈大小(S.stackSize),栈顶指针S.top(第一个元素的上面一个地址),栈底指针S.base,栈顶指针高于栈底指针(数量小于)
顺序栈的表示
typedef struct{
SElemType *top;
SElemType *base;
int stacksize;
}SqStack;
链栈的表示
typedef struct StackNode{
SElemType data;
struct stackNode* next;
}StackNode,*LinkStack;
LinkStack S;
链栈是运算受限的单链表,只能在链表头部进行操作,故没有必要附加头节点,头指针就是链栈的头节点
空栈就是栈顶指针置空(头指针数据部不是空的)
基本操作
顺序栈初始化
(1)分配空间并检查空间是否分配失败,若失败返回false
(2)设置栈底和栈顶指针
S.top=S.base
(3)设置栈大小
S.stacksize=MAXSIZE
Status InitStack(SqStack &S){
S.base=new SElemtype[size];
if(!S.base) return False;
S.top=S.base;
S.stackSize=size;
return True;
}
计算栈的长度
S.top-S.base;
清空顺序栈
S.top=S.base
销毁顺序栈
if(S.base){
delete S.base;
S.stacksize=0;
S.base=S.top=NULL;
}
入栈
(1)判断是否栈满,若栈满返回false或分配更大的空间
if(S.top-S.base==S.stackSize)return false;
(2)元素e压入栈顶
*s.top=e
(3)栈顶指针加1
s.top++
出栈
(1)判断是否栈空
if(S.top==S.base)return false;
(2)获取栈顶元素e
e=*(S.top-1)
(3)栈顶指针减1
S.top–
或者:e=*(–S.top)
获取栈顶元素
1)判断是否栈空,空则返回错误
if(S.top==S.base)return false;
(2)获取栈顶元素e
e=*(S.top-1)
应用
数制转换
void conversion(){
InitStack(S);
scanf("%d",&N);
while(N){
Push(S,N%8);
N=N/8;
}
while(!StackEmpty(S)){
Pop(S,e);
printf("%d",e);
}
}
void conversion(int n){
if(n==0) return;
else{
concersion(n/2);
cout<<n%2;
}
}
栈与递归
时间效率
与递归树的深度成正比 O(n)
空间效率
与递归树的节点数(调用次数)成正比 O(2^n)
汉诺塔
#include<iostream.h>
int c=0;//第几个步骤
void move(char c,int n,char z){ //把C上编号为n的盘子移动到Z上
cout<<++c<<","<<n<<","<<x<<","<<z<<endl;
}
void Hanoi(int n,char A,char B,char C){//用B作为过渡,把A上n个盘子移动到C上
if(n==1)move(A,1,c);
else{
Hanoi(n-1,A,C,B);
move(A,n,C);
Hanoi(n-1,B,A,C);
}
}
求解迷宫
要解决的问题:迷宫的数据结构,试探方向,栈的设计,防止重复到达某点,避免发生死循环
迷宫的数据结构:二维数组
方向:后退为0,上前为1,左边是2,右边是3
栈的设计:
struct{
int direction;
int[][] position;
bool markprint=True;//能否走得通
}
队列
表示
顺序表示
#define MAXQSIZE 100
Typedef struct{
QElemType* base;
int front;
int rear;
}SqQueue;
数据元素
Q.front,Q.rear,front大小低于rear,rear指向的是最后一个元素的下一个
基本操作
空队标志:front=rear;
入队:base[rear++]=x;
出队:x=base[front++];
出队
x=base[front++]
入队
base[rear++]=x;
存在的问题【使用顺序表】
真溢出,假溢出
解决办法:
M是尾结点减去头节点,即整个数组的空间
入队:base[rear]=x;rear=(rear+1)%M;
出队:x=base[front];front=(front+1)%M;
判断队空队满:少用一个元素空间
队空:front==rear;
队满:(rear+1)%M==front
栈和队列区别
都是线性表,只是运算规则不一样,栈是后进先出,队列是先进先出
注意
头指针就是head,仅仅是一个指针,指向头节点,如图
头节点是为了操作的统一与方便而设立的,放在第一个元素结点之前,其数据域一般无意义(当然有些情况下也可存放链表的长度、用做监视哨等等)。
首元结点也就是第一个元素的结点,它是头结点后边的第一个结点。
单链表也可以没有头结点。如果没有头结点的话,那么单链表就会变成这样: