栈
栈(Stack)是一种线性表,只允许在一端进行插入或删除操作。特性:后进先出(LIFO)。
顺序栈
采用顺序存储的栈称为顺序栈。
#define MaxSize 50
typedef struct SqStack{
ElemType data[MaxSize];
int top; //栈顶指针
}SqStack;
栈顶指针:S.top,初始时设置S.top=-1;
进栈操作:栈不满时,栈顶指针先加1,再送值到栈顶元素
出栈操作:栈非空时,先取栈顶元素值,再将栈顶指针减1
栈空条件:S.top==-1;
栈满条件:S.top==MaxSize-1;
栈长:S.top+1
基本操作
(1)初始化
void InitStack(SqStack &S){
S.top=-1; //初始化栈顶指针
}
(2)判栈空
bool StackEmpty(SqStack S){
if(S.top==-1){
return true; //栈空
}
else{
return false;
}
}
(3)进栈
bool Push(SqStack &S,ElemType x){
if(S.top==MaxSize-1){
return false;
}
S.data[++S.top]=x; //指针先加1,再入栈
return true;
}
(4)出栈
bool Pop(SqStack &S,ElemType &x){
if(S.top==-1){
return false;
}
x=S.data[S.top--]; //先出栈,指针再减1
return true;
}
(5)读栈顶元素
bool GetTop(SqStack S,ElemType &x){
if(S.top==-1){
return fasle;
}
x=S.data[S.top];
return true;
}
共享栈
可以让两个顺序栈共享一个一维数据空间,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸。
链栈
优点:便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。
链栈没有头结点,Lhead指向栈顶元素。
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
练习
1.假设以I和O分别表示入栈和出栈操作。栈的初态和终态均为空,入栈和出栈的操作序列可表示为仅由I和O组成的序列,可以操作的序列称为合法序列,否则称为非法序列。
写出一个算法,判定所给的操作序列是否合法。若合法返回true,否则返回false
bool Judge(char A[]){
int j=0;
int i=0, o=0;
while(A[i]!='\0'){
//未到字符数组尾
switch(A[i]){
case 'I':i++;
break;
case 'O':o++;
if(o>i){
//序列非法,退出
exit(0);
}
}
i++;
}
if(i!=o){
return false;
}
else{
return true;
}
}
2.设单链表的表头指针为L,结点结构由data和next两个域构成,其中data域为字符型。试设计算法判断该链表的全部n个字符是否中心对称。例如xyx、xyyx。
bool Symmetry(LinkList L,int n){
int i;
char s[n/2]; //字符栈
p=L->next;
for(i=0;i<n/2;i++){
s[i]=p->data;
p=p->next;
}
i--;
if(n%2==1){
//n是奇数
p=p->next;
}
while(p!=NULL&&s[i]==p->data){
i--;
p=p->next;
}
if(i==-1){
return true;
}
else{
return false;
}
}
队列
队列(queue)。简称队,只允许在表的一端进行插入,另一端进行删除。操作特性:先进先出(FIFO)。
队头(front)。允许删除的一端,又称队首。
队尾(rear)。允许插入的一端。
顺序存储
分配一块连续的存储单元存放队列中的元素,并附设两个指针front和rear分别指向队头和队尾元素的位置。(也可以让front指向队头元素的前一个位置)
#define MaxSize 50 //定义队列元素的最大个数
typedef struct SqQueue{
ElemType data[MaxSize];
int front,rear;
}SqQueue;
循环队列
把存储队列元素的表从逻辑上视为一个环。当队首指针Q.front=MaxSize-1后,再前进一个位置就自动到0,可以利用除法取余运算(%)来实现。
初始:Q.front=Q.rear=0
队首指针进1:Q.front=(Q.front+1)%MaxSize
队尾指针进1:Q.front=(Q.rear+1)%MaxSize
队列长度:(Q.rear+MaxSize-Q.front)%MaxSize
判断队空和队满:
-
牺牲一个单元来区分队空和队满
队满条件:(Q.rear+1)%MaxSize==Q.front
队空条件:Q.rear==Q.front -
增加表示元素个数的数据成员。
队空条件:Q.size==0
队满条件:Q.size==MaxSize -
增加tag数据成员。tag等于0时,若因删除导致Q.front==Q.rear,则队空;tag等于1时,若因插入导致Q.front=