第四章 栈与队列

1.栈的定义

  定义:栈是只允许在一端进行插入和删除操作的线性表。后进先出(LIFO)

  栈顶:线性表允许进行插入和删除的那一端。

  栈底:固定的,不允许进行插入和删除的那一端。

  卡特兰数:n个元素进栈,一共会有C(n,2n)/(n+1)种不同的出栈结果。

2.队列的定义

  定义:队列也是一种操作受限的线性表,只允许在表的一端进行插入,在表的另一端进行删除。先进先出(FIFO)

  队头:允许进行删除的一端,又称为队首。

  队尾:允许进行插入的一端。

3.顺序栈的定义及特点

  定义:采用顺序存储的栈称为顺序栈,它是利用一组连续的存储单元存放自栈底到栈顶的数据元素,同时附设一个指针(top)指示当前栈顶元素的位置。

  特点:当对栈的最大使用空间估计不足时,有可能会发生栈上溢。

4.链式栈的定义及特点

  定义:采用链式存储的栈称为链栈。

  特点:优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。在表头进行插入和删除。

5.顺序队列的定义及特点

  定义:队列的顺序实现是指分配一块连续的存储单元存放队列中的元素,并附设两个指针:队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置。

  特点:连续的存储单元存放。

6.链式队列的定义及特点

  定义:队列的链式表示为链队列,它实际上是一个同时带有队头指针和队尾指针的单链表。头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点。

  特点:不存在队列溢出的情况。

7.栈的应用

  (1)栈在括号匹配中的应用

    遇到左括号就入栈,遇到有括号就从栈中取出一个左括号匹配。

  (2)栈在表达式求值的应用

    后缀表达式中,遇到数字就入栈,遇到运算符就从栈中取出两个数字运算,运算结果在放回栈中。

  (3)栈在递归中的应用

    条件:

      (1)递归表达式(递归体)

      (2)边界条件(递归出口)

    递归的精髓在于能否将原始问题转换为属性相同规模较小的问题。

    优点:代码简单,容易理解。

    缺点:递归次数过多容易造成栈溢出。

    例题:

      

 1 int Fib(int n){
 2     if(n == 0){            //边界条件 
 3         return 0;
 4     }
 5     else if(n == 1){    //边界条件 
 6         return 1;
 7     }
 8     else{
 9         return Fib(n-1) + Fib(n-2);
10     }
11 } 

8.队列的应用

    (1)队列在层次遍历中的应用

  (2)队列在计算机系统中的应用

     FCFS(先来先服务)

9.顺序存储结构对栈基本操作的实现

(1)结构体定义

1 #define MaxSize 50
2 typedef struct{
3     ElemType data[MaxSize];
4     int top;
5 }SqStack;

(2)栈的初始化

1 void InitStack(SqStack &S){
2     S.top = -1;
3 }

(3)进栈

1 bool Push(SqStack &S, ElemType x){
2     if(S.top == MaxSize -1){
3         return false;
4     }
5     S.data[++S.top] = x;
6     return true;
7 }

(4)出栈

1 bool Pop(SqStack &S, ElemType &e){
2     if(S.top == -1){
3         return false;
4     }
5     e = S.data[S.top--];
6     return true;
7 }

10.顺序存储结构对队列基本操作的实现

(1)结构体的定义

1 #define MaxSize 50
2 typedef struct{
3     ElemType data[MaxSize];
4     int front,rear;
5 }SqQueue;

(2)队列判空

1 bool isEmpty(SqQueue Q){
2     if(Q.rear == Q.front)    
3         return true;
4     else 
5         return false;
6 }

11.链式存储结构对栈基本操作的实现

(1)结构体定义

1 typedef struct Linknode{
2     ElemType data;
3     struct Linknode *next;
4 }*LiStack

12.链式存储结构对队列基本操作的实现

(1)结构体定义

1 typedef struct{                    //链式队列结点 
2     ElemType data;
3     struct LinkNode *next;
4 }LinkNode;
5 typedef struct{                    //链式队列指针 
6     LinkNode *front,*rear;
7 }LinkQueue;

(2)链式队列初始化

1 void InitQueue(LinkQueue &Q){
2     Q.front = Q.rear = (LinkNode *)malloc(sizeof(LinkNode));
3     Q.front ->next = NULL;
4 } 

(3)链式队列入队

1 void EnQueue(LinkQueue &Q, ElemType x){
2     LinkNode *s = (LinkNode *)malloc(sizeof(LinkNode));
3     s->data = x;
4     s->next = NULL;
5     Q.rear->next = s;
6     Q.rear = s;
7 }

(4)链式队列出队

 1 bool DeQueue(LinkQueue &Q, ElemType &e){
 2     if(Q.front == Q.rear)            //空队 
 3         return false;
 4     LinkNode *p = Q.front->next;    //p->队头元素 
 5     e = p->data;
 6     Q.front->next = p->next;
 7     if(Q.rear == p){
 8         Q.rear = Q.front;
 9     }
10     free(p);
11     return true;
12 }

13.顺序存储结构中实现循环队列

  初始化:Q.front = Q.rear = 0

  出队:Q.front = (Q.front+1)%MaxSize

  入队:Q.rear = (Q.rear+1)%MaxSize

  为了区分队空队满的三种方式:

    (1)牺牲一个单元来区分队空和队满(队头指针在队尾指针的下一个位置作为队满的标志)

    (2)类型中新增表示元素个数的数据成员。如Q.size = 0等。

    (3)类型中新增tag数据成员,以区分是队满还是队空。

      tag=0时,front=rear表示队空;

      tag=1时,front=rear表示队满;

(1)循环队列入队

1 bool EnQueue(SqQueue &Q, ElemType x){
2     if((Q.rear+1)%MaxSize == Q.front){
3         return false;
4     }
5     Q.data[Q.rear] = x;
6     Q.rear = (Q.rear+1)%MaxSize;
7     return true;
8 }

(2)循环队列出队

1 bool DeQueue(SqQueue &Q, ElemType &e){
2     if(Q.rear == Q.front){
3         return false;
4     }
5     e = Q.data[Q.front];
6     Q.front = (Q.front-1)%MaxSize;
7     return true;
8 }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空梦♡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值