数据结构 第三章 栈和队列
3.1
栈的顺序存储结构
顺序栈的实现
顺序存储
# define MaxSize 50
typedef struct{
Elemtype data[MaxSize];
int top; //栈顶指针
}SqStack;
栈顶指针:S.top,初始时设置S.top=-1;
栈顶元素:S.data[S.top];
进栈操作:栈不满时,栈顶指针先加1,再赋值到栈顶元素;
出栈操作:栈非空时,先取栈顶元素值,再将栈顶指针减1;
栈空条件:S.top==-1;
栈满条件:S.top==MaxSize-1;
栈长:S.top+1
初始化
void InitStack(SqStack &S){
S.top=-1;
}
判断栈空
bool StackEmpty(SqStack S){
return S.top==-1
}
进栈
bool Push(SqStack &S, ElemType x){
if(S.top==MaxSize-1)
return false;
S.data[++S.top]=x;
return true;
}
出栈
bool Pop(SqStack &S, ElemType &x){
if(S.top==-1)
return false;
x=S.data[S.top--]
return true;
}
读栈顶元素
bool GetTop(SqStack S, ElemType &x){
if(S.top==-1)
return false;
x=S.data[S.top];
return true;
}
共享栈
栈底位置相对不变,两个顺序栈共享一个一维数组,将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间中间延伸。
top0=-1 0号栈为空;top1=MaxSize 1号栈为空
当top1-top0=1时,栈满。
0号栈进栈,top0先+1后赋值;1号栈进栈,top1先-1再赋值。
栈的链式存储结构
定义
typedef struct Linknode{
ElemType data;
struct Linknode *next;
}*LiStack;
习题3.1
CDEBA
CDBEA
CDBAE
BCAED可,其操作为A进、B进、C进、C出、B出、D进、E进、E出、D出、A出
DBACE不可,因为D最先出,说明栈内已经有ABC,则B和A不可能在C前出。
1)A、C、D合法
2)
int judge(ElemType A, int n){
int count = 0;
for(int i=0;i<n;i++){
if(A[i]=='I')
count++;
else
count--;
if(count < 0)
return 0;
}
return 1;
}
int dc(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--; //恢复最后的i值
if(n%2==1)
p=p->next;
while(p!=NULL&&s[i]==p->data){
i--;
p=p->next;
}
if(i==-1)
return 1;
else
return 0;
}
入栈
int push(int i, elemtp x){
if(i<0||i>1){
printf("栈号输入不对");
exit(0);
}
if(s.top[1]-s.top[0]==1){
printf("栈已满\n");
return 0;
}
switch(i){
case 0: s.stack[++s.top[0]]=x;
return 1;
break;
case 1: s.stack[--s.top[1]]=x;
return 1;
}
}
出栈
int pop(int i, elemtp x){
if(i<0||i>1){
printf("栈号输入不对");
exit(0);
}
switch(i){
case 0:
if(s.top[0]==-1){
printf("0栈空\n");
return -1;
}
else
return s.stack[s.top[0]--];
break;
case 1:
if(s.top[1]==maxsize){
printf("1栈空\n");
return -1;
}
else
return s.stack[s.top[1]++]
}
}
3.2
队列的顺序存储结构
队列的顺序存储
队列的顺序实现:分配一块连续的存储单元存放队列中的元素,并附设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置。
#define MaxSize 50
typedef struct{
ElemType data[MaxSize];
int front, rear;
}SqQueue;
初始状态(队空条件):Q.frontQ.rear0;
进队操作:队不满时,先送值到队尾元素,再将队尾指针+1;
出队操作:队不空时,先取队头元素,再将队头指针+1;
单纯的队列会导致假溢出,明明有存储空间,但因为指针指向队尾,无法再向队列中存放元素
循环队列
初始状态:Q.frontQ.rear0;
队首指针进1:Q.front=(Q.front+1)%MaxSize;
队尾指针进1:Q.rear=(Q.rear+1)%MaxSize;
队列长度:(Q.rear+MaxSize-Q.front)%MaxSize
出队入队时:指针都按顺时针方向进1
由于队空和队满有三种处理方式:
- 牺牲一个单元来区分队空和队满,入队时少用一个队列单元,约定以“队头指针在队尾指针的下一位置作为队满的标志”,
队满条件:(Q.rear+1)%MaxSizeQ.front
队空条件:Q.frontQ.rear
队列中元素的个数:(Q.rear-Q.front+MaxSize) %MaxSize - 类型中增设一个元素个数。这样队空条件为Q.size0;队满的条件为Q.sizeMaxSize.(都可能出现Q.front==Q.rear)
- 类型中增设tag,区分队满队空,tag=0时,若因删除导致Q.frontQ.rear,则为队空;tag=1时,若因插入导致Q.frontQ.rear,则为队满。
初始化
void InitQueue(SqQueue &Q){
Q.rear=Q.front=0;
}
判断队空
bool isEmpty(SqQueue Q){
if(Q.rear=Q.front)
return true;
else return false;
}
入队
bool EnQueue(SqQueue &Q, ElemType x){
if((Q.rear+1)%MaxSize==Q.front)
return false;
Q.data[Q.rear]=x'
Q.rear=(Q.rear+1)%MaxSize
}
出队
bool DeQueue(SqQueue &Q, ElemType &x){
if(Q.rear==Q.front)
return false;
x=Q.data[front];
Q.front=(Q.front+1)%MaxSize;
return true;
}
队列的链式存储结构
队列的链式存储
队列的链式表示是一个同时带有队头指针和队尾指针的单链表。
typedef struct{
ElemType data;
struct LinkNode *next;
}LinkNode;
typedef struct{
LinkNode *front, *rear;
}LinkQueue;
当Q.frontNULL&&Q.rearNULL时,链式队列为空。
单链表的链式队列表示适合于数据元素变动比较大的情形,且不存在列满溢出的情况。
链式队列的基本操作
初始化
void InitQueue(LinkQueue &Q){
Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));
Q.front->next=NULL;
}
判队空
bool IsEmpty(LinkQueue Q){
if(Q.front==Q.rear)
return true;
else
return false;
}
入队