栈(Stack)和队列(Queue)

栈与队列

      • 1、栈(先进后出)
          • a.顺序栈
          • b.链式栈
          • c.基本操作(顺序存储)
      • 2、队列(先进先出)
          • a.顺序存储
          • b.链式存储
          • c.基本操作(链式存储)
          • d.循环队列
          • e.双端队列

1、栈(先进后出)

定义:只允许在一端 进行插入或者删除操作的线性表
基本结构图如下:
栈(Stack)和队列(Queue)_第1张图片

注:n个不同元素进入栈,能够获取:​​ C 2 n n n + 1 \dfrac {C^n_{2n}}{n+1} n+1C2nn(卡特兰数)个不同出栈序列

a.顺序栈

利用一组地址连续的存储单元存放自栈底栈顶的数据元素

#define MaxSize 50 //定义栈的空间大小
typedef struct{
	int data[MaxSize]; //存储元素
	int top; //栈顶指针
}SqStack;

注意:1、空栈条件top == -1;
2、栈满条件S.top == MaxSize-1;

b.链式栈

通常情况栈的插入和删除在表头进行,链式结构如下

在这里插入图片描述

typedef struct Linknode{
	int data; //数据域
	struct Linknode *next; //指针域
}*LiStack;

注意:1、在进行数据结构类条件判断时,需注意指针所对应的初始位置。指针指向会影响到对应操作(如此处的栈空、栈满条件)
2、空栈top == NULL;
3、不存在栈满溢出情况

c.基本操作(顺序存储)
  1. 初始化
void InitStack(SqStack &S){
	S.top = -1; //初始化栈顶指针
}
  1. 判断栈空
bool IsEmpty(SqStack S){
	if(S.top == -1)
		return true; //栈空
	else
		return false;
}
  1. 进栈
bool Push(SqStack &S, int x){
	if(S.top == MaxSize-1) //栈满?
		return false;
	S.data[++S.top] = x; //指针加1,然后入栈
	return true;
}
  1. 出栈
bool Pop(SqStack &S, int &x){
	if(S.top == -1) //栈空?
		return false;
	x = S.data[S.top--]; //先出栈,指针减1
	return true;
}

2、队列(先进先出)

定义:单向进行插入、删除的线性表
栈(Stack)和队列(Queue)_第2张图片

注意:队列操作,不可以随意读取队列中的某个数据。

a.顺序存储
#define MaxSize 50  //定义元素的最大个数
typedef struct{
	int data[MaxSize]; //存放队列元素
	int front, rear; //队头指针和队尾指针
}SqQueue;
b.链式存储
typedef struct{ //链式队列结点
	int data;
	struct LinkNode *next;
}LinkNode;
typedef struct{ //链式队列
	LinkNode *front,*rear;
}LinkQueue;
c.基本操作(链式存储)
  1. 初始化
void InitQueue(LinkQueue &Q){
	Q.front = Q.rear = (LinkNode*)malloc(sizeof(LinkNode)); //建立头结点
	Q.front->next = NULL; 
}
  1. 判断队空
bool IsEmpty(LinkQueue Q){
	if(Q.front == Q.rear)
		return true;
	else 
		return false;
}
  1. 入队
void EnQueue(LinkQueue &Q, int x){
	LinkNode *s = (LinkNode*)malloc(sizeof(LinkNode));
	s->data = x; //创建新结点,插入到链尾
	s->next = NULL;
	Q.rear->next = s;
	Q.rear = s;
}
  1. 出队
bool DeQueue(LinkQueue &Q, int &x){
	if(Q.front == Q.rear) return false; //空队
	LinkNode *p = Q.front->next;
	x = p->data;
	Q.front->next = p->next;
	if(Q.rear == p)
		Q.rear = Q.front; //原队列只有一个结点,删除后变空
	free(p);
	return true;
}
d.循环队列

(引入循环队列,为了防止判别队满情况时出现“假溢出”现象)
入队:rear = (rear+1)%MaxSize //队尾指针加1
出队:front = (front+1)%MaxSize //队首指针加1
队列长度:(rear+Maxsize-front)%Maxsize

判断队空队满

  1. 入队时少用一个队列单元
    队满:(Q.rear+1)%Maxsize == Q.front
    队空:Q.front = = Q.rear
  2. 增设表示元素个数的数据成员
    队满:Q.size == Maxsize
    队空:Q.size = = 0
  3. 增设tag数据成员
    tag为0时,若删除操作导致Q.front == Q.rear,为队空
    tag为1时,若插入操作导致Q.front = = Q.rear,为队满
e.双端队列

引用别人的一张图说明
栈(Stack)和队列(Queue)_第3张图片


考研小注:

  1. 判断出栈序列合法性
  2. 循环队列的原理和性质
  3. 进队和出队的操作
  4. front和rear初值(不固定)的推断
  5. 队列中元素个数的计算
  6. 判空和判满的条件
  7. 输出受限、输入受限的双端队列的出队序列合法性
  8. 栈和队列的应用及特点
  9. 出入栈的过程中栈的至少容量
  10. 栈在递归中的应用
  11. 栈在表达式求值中的应用
  12. 中缀表达式转为后缀表达式
  13. 特殊矩阵(对称矩阵、上三角矩阵、下三角矩阵)的压缩存储

小狼的相关博文:
14. 算法(Algorithm)与数据结构(Data Structure)——索引

  1. 数据结构和算法系列代码测试代码

你可能感兴趣的:(数据结构)