数据结构——栈,队列和数组

news/2024/10/21 9:53:52/

文章目录

    • **一 栈**
      • **1 基本概念**
      • **2 栈的顺序存储结构**
        • **2.1 顺序栈的实现**
        • **2.2 顺序栈的基本运算**
        • **2.3 共享栈**
      • **3 栈的链式存储结构**
    • **二 队列**
      • **1 基本概念**
      • **2 队列的顺序存储结构**
        • **2.1 队列的顺序存储**
        • **2.2 循环队列**
        • **2.3 循环队列的操作**
      • **3 队列的链式存储结构**
        • **3.1 队列的链式存储**
        • **3.2 链式队列的基本操作**
      • **4 双端队列**
    • **三 栈和队列的应用**
      • **1 栈的括号匹配问题**
      • **2 栈的表达式求值问题**
      • **3 栈的递归问题**
      • **4 队列的层序遍历问题**
      • **5 队列的计算机系统的应用**
    • **四 数组和特殊矩阵**
      • 1 数组
      • **2 特殊矩阵的压缩存储**
        • **2.1 对称矩阵**
        • **2.2 三角矩阵**
        • **2.3 三对角矩阵**
        • **2.4 稀疏矩阵**

一 栈

1 基本概念

栈是一种线性表,但是只能在一端插入或者删除,而且栈是先进后出(后进先出)的

n个不同元素的排列个数有1/(n+1)*C2nn

在这里插入图片描述

基本操作:

Initstack(&S);           \\初始化一个空栈
Stackempty(S);           \\判空
push(&S,X);              \\进栈
pop(&s,&x);              \\出栈
gettop(&s,&x);           \\读栈顶元素
destroystack(&s);        \\销毁栈

2 栈的顺序存储结构

2.1 顺序栈的实现

采用顺序存储,利用一组地址连续的存储单元存放,设一个指针指示当前栈顶元素的位置

#define maxsize 50
typedef struct
{elemtype data[maxsize];int top;                        \\初始为-1
}Sqstack;

受数组上限的约束,可能发生溢出

2.2 顺序栈的基本运算

在这里插入图片描述

(1)初始化

viod Initstack(sqstack &s)
{s.top=-1;
}

(2)判空

bool stackempty(sqstack &s)
{if(s.top==-1)return true;elsereturn false;
}

(3)进栈

bool push(sqstack &s,elemtype x)
{if(s.top==maxsize-1)return false;s.data[++s.top]=x;return true;
}

(4)出栈

bool pop(sqstack &s,elemtype &x)
{if(s.top==-1)return false;x=s.data[s.top--];return true;
}

(5)读栈顶元素

bool gettop(sqstack s,elemtype &x)
{if(s.top==-1)return false;x=s.data[s.top];return true;
}

2.3 共享栈

两个顺序栈共享一个一维数组

在这里插入图片描述

top0=-1时0号栈为空,top1=maxsize时1号栈为空

仅当两个栈顶指针相邻,top1-top0=1时,栈满

0号栈进栈,top0先加1再赋值;1号栈进栈top1先减1再赋值;出栈时相反

3 栈的链式存储结构

称为链栈,便于多个栈共享存储空间和提高效率,且不存在栈满上溢的情况,通常用单链表实现,规定所有操作在表头进行

没有头结点,Lhead指向栈顶元素

在这里插入图片描述

typedef struct Linknode
{elemtype data;struct  Linknode  *next;
}*Listack;

二 队列

1 基本概念

也是一种操作受限的线性表,但是只允许一端插入,一端删除,即先进先出

在这里插入图片描述

Initqueue(&Q);            \\初始化
Queueempty(Q);            \\判空
Enqueue(&Q,x);            \\入队
Dequeue(&Q,&x);           \\出队
Gethead(Q,&x);            \\读队头元素

栈和队列都不能随意读取中间的元素

2 队列的顺序存储结构

2.1 队列的顺序存储

分配一块连续的存储单元,设两个指针,队头指针front指向队头元素,队尾指针rear指向队尾元素的下一个位置

#define maxsize 50
typedef struct
{elemtype data[maxsize];int front,rear;            \\初始都为0
}Sqqueue;

不能用Q.rear==maxsize来判断队列满的条件,如图

在这里插入图片描述

2.2 循环队列

由顺序队列的缺点,引出循环队列

将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,利用除法取余运算来实现

队首指针进1:Q.front=(Q.front+1)%maxsize

队尾指针进1:Q.rear=(Q.rear+1)%maxsize

队列长度:(Q.rear+maxsize-Q.front)%maxsize

出队入队时指针都要按顺时针方向进1

判空可以用Q.front=Q.rear,但是满队时也有Q.front=Q.rear,如图

在这里插入图片描述

区分队空还是队满的解决方法:

(1)牺牲一个单元来区分,入队时少用一个队列单元,约定以队头指针再队尾指针的下一个位置作为队满的标志

队满:(Q.rear+1)%maxsize==Q.front

队空:Q.front==Q.rear

队列元素的个数:(Q.rear+maxsize-Q.front)%maxsize

(2)增设表示元素个数的成员size

队空:Q.size==0

队满:Q.size == maxsize

两种情况都有Q.front==Q.rear

(3)增设tag数据成员

tag=0,若因删除导致Q.front==Q.rear,队空

tag=1,若因插入导致Q.front==Q.rear,队满

2.3 循环队列的操作

(1)初始化

void Iinitqueue(Sqqueue &Q)
{Q.rear=Q.front=0;
}

(2)判空

bool isempty(Sqqueue Q)
{if(Q.rear==Q.front)return true;elseruturn false;
}

(3)入队

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;return true;
}

(4)出队

bool Dequeue(Sqqueue &Q,elemtype &x)
{if(Q.rear == Q.front)return false;x=Q.data[Q.front];Q.front=(Q.front+1)%maxsize;return true;
}

3 队列的链式存储结构

3.1 队列的链式存储

实际上是一个同时带有队头指针和队尾指针的单链表,头指针指向队头结点,尾指针指向队尾结点,即单链表的最后一个结点

typedef struct Linknode           \\队列结点
{elemtype data;struct Linknode *next;
}Linknode;typedef struct                    \\链式队列
{Linknode *front,*rear;
}*LinkQueue;

Q.front==NULL,Q.rear==NULL时队列为空

通常设计为带头结点,统一删除和插入操作;适合于数据元素变动比较大的情形

在这里插入图片描述

3.2 链式队列的基本操作

(1)初始化

void Initqueue(Linkqueue &Q)
{Q.front = Q.rear=(Linknode*)malloc(sizeof(Linknode));   \\建立头结点Q.front->next=NULL;                                     \\初始为空
}

(2)判空

bool isempty(Linkqueue Q)
{if(Q.front==Q.rear)return true;elsereturn false;
}

(3)入队

void Enqueue(Linkqueue &Q,elemtype x)
{Linknode *s=(Linknode*)malloc(sizeof(Linknode));s->data=x;s->next=NULL;Q.rear->next=s;Q.rear=s;
}

(4)出队

bool Dequeue(Linkqueue &Q,elemtype &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;
}

4 双端队列

允许两端都可以进行入队和出队操作,逻辑结构仍是线性结构

在这里插入图片描述

输出受限:

在这里插入图片描述

输入受限:

在这里插入图片描述

三 栈和队列的应用

1 栈的括号匹配问题

在这里插入图片描述

2 栈的表达式求值问题

在这里插入图片描述

在这里插入图片描述

3 栈的递归问题

int fib(int n)                      \\递归实现斐波那契数列
{if(n==0)return 0;else if (n==1)return 1;elsereturn fib(n-1)+fib(n-2);
}

但是递归次数过多容易造成栈溢出,转换为非递归需要借助栈

4 队列的层序遍历问题

在这里插入图片描述

在这里插入图片描述

5 队列的计算机系统的应用

(1)解决主机与外部设备之间速度不匹配的问题

设置一个数据缓冲区,这个缓冲区存储数据就是一个队列

(2)解决多用户引起的资源竞争问题

按请求的先后顺序入队

四 数组和特殊矩阵

1 数组

数组是线性表的推广,以为数组可视为一个线性表,二维数组可视为其元素也是定长线性表的线性表

对于多维数组,有两种存储映射方式,按行优先和按列有限

2 特殊矩阵的压缩存储

压缩存储:为多个值相同的元素只分配一个存储空间,对零元素不分配空间

常见的特殊矩阵:对称矩阵,上(下)三角矩阵,对角矩阵

2.1 对称矩阵

在这里插入图片描述

元素下标的对应关系

k=i(i-1)/2+j-1,i ⩾ \geqslant j,下三角区和主对角线元素

k=j(j-1)/2+i-1,i<j,上三角区元素aij=aji

下标从1开始

2.2 三角矩阵

在这里插入图片描述

下三角矩阵

k=i(i-1)/2+j-1,i ⩾ \geqslant j,下三角区和主对角线元素

k=n(n+1)/2,i<j,上三角区元素(常数项)

在这里插入图片描述

上三角矩阵

k=(i-1)(2n-i+2)/2+j-i,i ⩽ \leqslant j,上三角区和主对角线元素

k=n(n+1)/2,i>j,下三角区元素(常数项)

在这里插入图片描述

下标从0开始

2.3 三对角矩阵

在这里插入图片描述

下标:k=2i+j-3

反之若知道k,则 i=(k+1)/3+1,向下取整

j=k-2i+3

2.4 稀疏矩阵

矩阵中非零个数非常少

为节省空间,将非零元素和相应的行和列构成一个三元组(行,列,值)

但是不能随机存取

在这里插入图片描述


http://www.ppmy.cn/news/305982.html

相关文章

浩顺考勤机二次开发(第二版,附实测可用的demo)

1.背景 之前写过一次浩顺考勤机的二次开发,不过那个版本还是有一些问题,后来更换了新的考勤机,又拿到了新的二次开发包,所以就有了这次这个版本 2.关于考勤机的一些说明 2.1 首先要给考勤机设定ip&#xff0c;通过网络访问考勤机。使用考勤机自带的软件读取一次数据&#xff0c…

java二次开发考勤机_浩顺AC671指纹考勤机二次开发(demo)

关于考勤机 AC671,是新换的机器,以前的那部机器,通过网络死活连接不上,换了AC671网络连接是好用了.但是,我要吐槽 浩顺的考勤机应该是卖了很多了吧,可是自带的软件太不给力,最后分析出来的数据一大堆,并不好用.so,试试看二次开发 联系卖家要来了二次开发包,是一个EXE文件,安装,…

CKA 07_Kubernetes 工作负载与调度 控制器 ReplicaSet Deployment Jobs CronJob

文章目录 1. Pod 的分类2. 控制器类型3. ReplicaSet3.1 工作原理3.2 何时使用 ReplicaSet3.3 创建 ReplicaSet3.4 修改 RS 管理 pod 的标签3.5 还原 RS 管理 pod 的标签 4. Deployment4.1 准备工作4.2 用例4.3 创建 Deployment4.4 Deployment 进行 Pod 的版本更新4.5 Deploymen…

JAVA中如何使用Socket 实现聊天功能?带具体代码说明

Java Socket 是 Java 标准库中用于网络编程的一种方式&#xff0c;通过 Socket 实现可以在不同的计算机之间进行数据传输。在聊天应用中&#xff0c;Socket 可以用来建立客户端和服务器之间的连接&#xff0c;实现用户之间的聊天交流。 一、建立服务器端 在建立服务器端时&am…

电脑联想小新连上蓝牙耳机依然外放,终于解决了

1、打开蓝牙设置 2、 拉到下面&#xff0c;点击 设备和打印机 3、找到 未指定/设备 里的蓝牙耳机。如果 设备 里未显示蓝牙耳机&#xff0c;点击 未指定 里蓝牙耳机的属性-服务&#xff0c;勾选音频接收器&#xff0c;设备里就会显示蓝牙耳机。 4、右击设备里的蓝牙耳机&#x…

联想S41-70拆机换内存条

注意&#xff1a; - 此机型只有一个内存卡槽 - 最大支持8G内存 步骤&#xff1a; 1、拧开后盖上的螺丝钉 2、用一字螺丝刀从插网线的口子出慢慢撬开后盖&#xff0c;一点一点来&#xff0c;不要急 3、将除了转轴其他三边都撬开之后&#xff0c;慢慢将后盖从转轴相对那边抬起…

联想笔记本e480恢复出厂设置_联想ThinkPad E480笔记本win10怎么改win7

[文章导读]联想ThinkPad E480是一款14寸笔记本,其搭载intel 酷睿第八代处理器的笔记本。预装的是win10系统,用户还是喜欢win7系统,该笔记本采用的第八代酷睿CPU,在安装WIN7过程中USB设备不能使用,且intel 8代没有发布win7的核心显卡驱动,所以需要采用win7新机型安装,那么…

thinkpad E470 安装ubuntu16.04双系统

小白thinkpad E470 安装ubuntu16.04双系统 刚拿到公司的电脑&#xff0c;被要求装个linux系统&#xff0c;连进入boot的快捷键是哪个都不知道&#xff0c;全程靠百度。 联想Thinkpad E470笔记本如何设置U盘启动&#xff1f;E470如何进入Bios设置U盘启动&#xff1a;http://www…