栈和队列

第三章 栈和队列

3.1 栈和队列的定义和特点

3.1.1 栈的定义和特点

表头 - 栈顶

表尾 - 栈底

只能从栈底进行插入和删除 后进先出LIFO

3.1.2 队列的定义和特点

队尾插入 队头删除

先进先出FIFO

3.2 案例

3.3 栈的表示和操作的实现

3.3.1 栈的类型定义

栈的两种表示方法:顺序栈和链栈。

3.3.2 顺序栈的表示和实现

顺序栈受最大空间限制

栈空标志base == top

栈满标志top - base == MAXSIZE

定义:

#define MAXSIZE = 100
typedef struct {
	SElemType *base;
	SElemType *top;
	int stacksize;
} SqStack;
  1. 初始化

定义的top指向栈顶元素的上一个位置 栈空时top和base都指向栈底

Status InitStack(SqStack &S) {
	S.base = new SElemType[MAXSIZE]; // 分配存储空间
	if(!S.base) exit(overflow); // 空间分配失败
	S.top = S.base;
	S.stacksize = MAXSIZE;
	return OK;
}
  1. 入栈

    Status Push(SqStack &S, SElemType e) {
    	if(S.top - S.base == S.stacksize) return ERROR;
    	*S.top++=e; // e压入栈顶 栈顶指针自加1
    	return OK;
    }
    
  2. 出栈

    Status Pop(SqStack &S, SElemType &e) {
    	if(S.top == S.base) return ERROR;
    	e = *--S.top;
    	return OK;
    }
    
  3. 取栈顶元素

    SElemType GetTop(SqStack S) {
    	if(S.top != S.base) return *(S.top - 1);
    	// 注意栈顶指针不变 只返回栈顶元素的值
    }
    

3.3.3 链栈的表示和实现

定义:

typedef struct StackNode{
	ElemType data;
	struct StackNode *next;
} StackNode, *LinkStack;
  1. 初始化

    Status InitStack(LinkStack &S) {
    	S = NULL;
    	return OK;
    }
    
  2. 入栈

不用判断栈是否满 因为链栈不会满

Status Push(LinkStack &S, SElemType e) {
	p = new LinkNode;
	p -> data = e;
	p -> next = S;
	S = p; // 修改栈顶指针
	return OK;
}
  1. 出栈
Status Pop(LinkStack &S, SElemType &e) {
	if(S == NULL) return ERROR;
	e = S -> data;
	p = S; // 暂存栈顶元素空间 以备后续释放
	S = S -> next;
	delete p; // 释放原栈顶元素空间
	return OK;
}

需要判断栈是否为空

  1. 取栈顶元素

    SElemType GetTop(SqStack S) {
    	if(S.top != S.base) return *(S.top - 1);
    }
    

3.4 栈与递归

3.4.1 递归解决的问题

分治法:

(1)有明确的递归出口(结束条件)

(2)问题可以转化为一个新问题,与原问题解法类似,而且处理对象更小且变化有规律

void p(参数表) {
    if(递归条件不成立) p(较小的参数表);
}

3.5 队列的表示和操作的实现

3.5.1

3.5.2 循环队列

初始化:front = rear = 0

定义头指针指向队头 尾指针指向队尾元素的下一个位置

循环队列:解决数组越界造成的假溢出问题

循环队列判断队满还是队空:

  1. 少用一个元素空间

    队满:Q.front == Q.rear

    队空:(Q.rear + 1) % MAXQSIZE == Q.front

  2. 另设标志位

循环队列操作的实现:

  1. 初始化

    Status InitQueue(SqQueue &Q) {
    	Q.base = new QElemType[MAXSIZE];
    	if(!Q.base) exit(OVERFLOW);
    	Q.front = Q.rea = 0;
    	return OK;
    }
    
  2. 求队列长度

    int QueueLength(SqQueue Q) {
    	return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
    }
    
  3. 入队

    Status EnQueue(SqQueue &Q, QElemType e) {
    	if((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR;
    	Q.base[Q.rear] = e;
    	Q.rear = (Q.rear + 1) % MAXQSIZE;
    	return OK;
    }
    
  4. 出队

    Status DeQueue(SqQueue &Q, QElemTypr &e) {
    	if(Q.front == Q.rear) return ERROR;
    	e = Q.base[Q.front];
    	Q.front = (Q.front + 1) % MAXQSIZE;
    	return OK;
    }
    
  5. 取队头元素

    SElemType GetHead(SqQueue Q) {
    	if(Q.front != Q.rear) return Q.base[Q.front];
    }
    

    设定循环队列时 必须为其设一个最大队列长度 如果无法预估 则应该采用链队

3.5.3 链队 队列的链式表示与实现

设置头结点;头指针始终指向头结点

  1. 初始化

    Status InitQueue(LinkQueue &Q) {
    	Q.front = Q.rear = new QNode;
    	Q.front -> next = NULL; // 头结点指针域置空
    	return OK;
    }
    
  2. 入队

    Status EnQueue(LinkQueue &Q, QElemType e) {
    	p = new QNode;
    	p -> data = e;
    	p -> next = NULL;
    	Q.rear = p;
    	return OK;
    }
    
  3. 出队

    Status DeQueue(LinkQueue &Q, QElemType &e) {
    	if(Q.front == Q.rear) return ERROR;
    	p = Q.front -> next;
    	e = p -> data;
    	Q.front -> next = p -> next;
    	if(Q.rear == p) Q.rear = Q.front;
    	delete p;
    	return OK;
    }
    
  4. 取队首元素

    SElemType GetHead(LinkQueue Q) {
    	if(Q.front != Q.rear) return Q.front -> next -> data;
    }
    
posted on 2023-10-11 22:23  ww0809  阅读(35)  评论(0)    收藏  举报