数据结构与算法基础(青岛大学-王卓)(4)

news2024/11/26 20:45:09

第四弹啊,栈和队列终于叮叮咚咚看完了,小龙虾呀鳝鱼汤啊倍儿香~~~~,配合本文食用更香 😃


文章目录

      • 栈和队列
        • 队列
        • 案列的引入
        • 栈的表示和操作
          • 栈的抽象数据类型定义
          • 顺序栈
            • 顺序栈的表示
            • 顺序栈的初始化
            • 顺序栈基本操作
            • 顺序栈的入栈
            • 顺序栈的出栈
          • 链栈
            • 链栈基本操作
        • 栈和递归
          • 递归的定义
          • 递归问题一用**分治法**求解
          • 递归优缺点
        • 队列的表示和操作
          • 队列的**抽象数据类型**定义
          • 循环队列(顺序表示)
            • 队列的真溢出和假溢出
            • 循环队列在队空和队满时的条件都为 front == rear, 如何分辨?
            • 循环队列的操作
          • 链队(链式表示)
            • 类型定义
            • 链队指针变化情况
            • 链队的基本操作

栈和队列

  • 栈和队列是限定插入和删除只能在表的“端点”进行的线性表

    • 他们都是线性表的子集(一种插入和删除受限的线性表)

      在这里插入图片描述

  • 栈的应用(后进后出)
    在这里插入图片描述

  • 队列的应用(先进先出)

    在这里插入图片描述

  • 栈(stack)是仅在表尾进行插入,删除的线性表,又称为后进先出(Last In First Out)的线性表,简称LIFO结构。

  • 表尾(an)称为栈顶Top, 表头(a1)称为栈底Base

  • 入栈(PUSH)

    在这里插入图片描述

  • 出栈(POP)

    在这里插入图片描述

  • 相关概念

    在这里插入图片描述

队列

  • 队列(queue)是一种先进先出(First In First Out) FIFO结构的线性表,表尾插入表头删除。

  • 相关概念

    在这里插入图片描述

案列的引入

  1. 进制转换 - “十进制整数N向其它进制数d(二,八,十六)的转换是计算机实现,该转换法则:除以d倒取余,对应于一个简单算法原理: n=(n div d)*d+n mod d (其中:div为整除运算,mod为求余运算)

    在这里插入图片描述

  2. 括号匹配的检验

    在这里插入图片描述

    在这里插入图片描述

  3. 舞伴问题

    在这里插入图片描述

栈的表示和操作

栈的抽象数据类型定义
ADT Stack{ 
    数据对象: D={ai|ai ∈ ElemSet,i=1,2...n,n>=0} 
    数据关系: R1={<ai-1,ai>|ai-1,ai∈D,i=2,...,n} 
    		约定an端为栈顶,a1端为栈底。 
    基本操作:初始化、进栈、出栈、取栈顶元素等 
}ADT Stack

在这里插入图片描述

顺序栈

存储方式,同一般线性表的顺序存储结构完全相同, 利用一组地址连续的存储单元依次存放自栈底 到栈顶的数据元素。栈底一般在低地址端。

  • 附设top指针,指示栈顶元素在顺序栈中的位置。

  • 另设base指针,指示栈底元素在顺序栈中的位置。

  • 但是,为了方便操作,通常top指示真正的 栈顶元素之上的下标地址

  • 另外,用stacksize表示栈可使用的最大容量

    在这里插入图片描述

  • 使用数组作为顺序栈的存储方式, 优点简单方便,但是容易溢出,

    • 空栈和栈满判断条件如下,分别会产生下面的溢出

    • 上溢(overflow): 栈已满还要压入元素 --> 属于错误,使问题无法进行

    • 下溢(underflow): 栈已空还要弹出元素 --> 看做结束条件

      在这里插入图片描述

    顺序栈的表示
    #define MAXSIZE 100
    typedef struct{
    	SElemType *base; / / 栈底指针
    	SElemType *top; / / 栈顶指针
    	int stacksize; / / 栈可用最大容量
    }SqStack;
    
    顺序栈的初始化

    在这里插入图片描述

    Status InitStack(SqStack &S) { //构造一个空栈
        S.base = new SElemType[MAXSIZE]; //c++
        S.base = (SElemType*)malloc(MAXSIZE*sizeof(SElemType)); // 或者c
        if(!S.base) exit(OVERFLOW); //存储分配失败时处理
        S.top = S.base; // 栈顶指针等于栈底指针
        S.stacksize = MAXSIZE;
        return OK;
    }
    
    顺序栈基本操作
    // 顺序栈判断栈是否为空
    Status StackEmpty(SqStack S){
        // 为空返回True
        if (S.top == S.base)
            return True;
        else
            return False;
    }
    
    // 顺序栈的长度
    int StackLength(SqStack S) {
        return S.top - S.base;
    }
    
    // 清空顺序栈
    Status ClearStack(SqStack S){
        if(S.base) S.top = S.base; // 清空不需要动数据,直接动top指针
        return OK;
    }
    
    // 销毁顺序栈
    Staus DestroyStack(SqStack &S){
        if (S.base) {
            delete S.base; // 这里代表释放S.base指针空间,并没有删除,变成了野指针,所以后面需要赋NULL值
            S.stacksize=0;
            S.top = S.base = NULL;
        }
        return OK;
    }
    
    顺序栈的入栈

    在这里插入图片描述

    顺序栈的出栈

    在这里插入图片描述

链栈
  • 链栈是运算受限的单链表,只能在链表头部进行操作

  • 链栈的表示

    在这里插入图片描述

    typede struct StackNode{
        SElemType data;
        struct StackNode *next;
    } StackNode, *LinkStack;
    LinkStack S;
    
    
    链栈基本操作
    // 链栈初始化
    Void InitStack(LinkStack &S){
        S=NULL; // 构造一个空栈,栈顶指针为空
        return OK;
    }
    
    // 判断链栈为空
    Status StackEmpty(LinkStack &S){
        if (S==NULL) return True;
        else retur False;
    }
    
    // 取栈顶元素
    SElemType GetTop(LinkStack S){
        if (S!=NULL) return S->data;
    }
    
    // 链栈的入栈
    Status PushStack(LinkStack &S, SElemType e){
        p = new StackNode; // 创建一个新的要插入的节点
        p.data = e; // data赋值
        p.next = S; // 新节点指向栈顶
        S = p; // 修改栈顶指针
        return OK;
    }
    
    // 链栈的出栈
    Status PopStack(LinkStack &S, SElemType &e){
        if (S==NULL) return ERROR;
        e=S->data; // 删除的元素给e
        p=S; 
        S=S->next; // 栈顶指针下移
        delete p; //删除原来的栈顶指针
        return OK;
    }
    

栈和递归

递归的定义
  • 若一个对象部分地包含它自己,或用它自己给自己定义,则称这个对象是递归的;

  • 若一个过程直接地或间接地调用自己则称这个过程是递归的过程。例如:递归求 n 的阶乘

  • 以下三种情况常常用到递归方法

    • 递归定义的数学函数

      在这里插入图片描述

    • 具有递归特性的数据结构

      在这里插入图片描述

    • 可递归求解的问题

      在这里插入图片描述

递归问题一用分治法求解

分治法 : 对于一个较为复杂的问题,能够分解成几个相对简单的且解法相同或类似的子问题来求解

  • 必备的三个条件

    • 能将一个问题转变成一个新问题,而新问题与原问题的解法相同或者类同、不同的仅是处理的对象,且这些处理对象是变化有规律的
    • 可以通过上述转化而使问题简化
    • 必须有一个明确的递归出口,或称递归的边界
  • 分治法的形式

    void p(参数表) {
        if (递归结束条件) 可直接求解步骤;--基本项
    	else P(较小的参数); --归纳项
    }
    

    Example:

    long Fact(long n){
        if (n==0) return 1;  //基本项
        else return n*Fact(n-1); //归纳项
    }
    

    在这里插入图片描述

递归优缺点

优点:结构清晰,程序易读

缺点:每次调用要生成工作记录,保存状态信息,入栈;返回时要出栈,恢复状态信息。时间开销大。

解决办法:

递归==>非递归

方法1:尾递归、单向递归 ==> 循环结构

在这里插入图片描述

在这里插入图片描述

方法2:自用栈 模拟 系统的运行时栈

在这里插入图片描述

在这里插入图片描述

队列的表示和操作

队列的抽象数据类型定义
ADT Queue{
	数据对象 :D = { ai|ai属于ElemSet,i=1,2...n,n>=0}
	数据关系 :R = {<ai-1,ai>|ai-1,ai属于D,i=1,2...,n} 约定其中 a1 端为队列头,an 端为队列尾 。
	基本操作 :
		lnitQueue(&Q)   操作结果 : 构造空队列 Q
		DestroyQueue(&Q) 条件 : 队列 Q 已存在 操作结果 : 队列 Q 被销毁
		ClearQueue(&Q) 条件 : 队列 Q 已存在  操作结果:将 Q 清空
		QueueLength(Q) 条件 : 队列 Q 已存在 操作结果 : 返回 0 的元素个数 , 即队长
		GetHead(Q (e) 条件 : Q 为非空队列 操作结果 : 用 e 返回 Q 的队头元素
		EnQueue()Q e) 条件 : 队列 Q 已存在 操作结果 : 插入元素 e 为 Q 的队尾元素
		DeQueue()Q (e) 条件 : Q 为非空队列 操作结果 : 删除 Q 的队头元素 , 用 e 返回值
        ...还有将队列置空 、 遍历队列等操作...
} ADT Queue
循环队列(顺序表示)
  • 一维数组base[MAXQSIZE]
#define MAXQSIZE 100 // 最大队列长度
Typedef struct {
    QElemType *base; // 初始化动态分配存储空间(指向数组首元素的指针)
    int front; // 头指针
    int rear; // 尾指针
}SqQueue;
队列的真溢出和假溢出

在这里插入图片描述

  • 解决假溢出问题 – 引入循环队列

    实现方法:利用模(mod,C语言中: %)运算

    插入元素: Q.base[Q.rear] = x;
    Q.rear=(Q.rear+1)%MAXQSIZE;

    删除元素: x=Q.base[s.front];
    Q.front=(Q.front+1)%MAXQSIZE;

    每当front/rear指针移动到最后位置的时候,通过模运算使其回到0,形成一个循环队列,可以循环使用为队列分配的存储空间。

    循环队列在队空和队满时的条件都为 front == rear, 如何分辨?
    • 另设一个标志来区别队空队满

    • 另设一个变量,记录元素个数

    • 少用一个元素空间(常用)队满:(rear+1)%MAXQSIZE==front

      在这里插入图片描述

循环队列的操作
// 队列的初始化
Status InitQueue(SqQueue &Q){
    Q.base=new QElemType[MAXQSIZE]; //分配数组空间
    // Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
    if(!Q.base) exit(OVERFLOW); //存储分配失败
    Q.front=Q.rear=0; //头尾指针为0,队列为空
    return OK;
}

// 求队列的长度
int QueueLength(SqQueue Q){
    return (Q.rear-Q.front+MAXQSIZE)%MAXQSZIE; // 需要考虑Q.rear比Q.front小的情况
}

// 循环队列入队
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;
}

// 循环队列的出队
Status DeQueue(SqQueue &Q, QElemType &e){
    if (Q.read==Q.front) return ERROR; 判断是否队空
    e=Q.base[Q.front];
    Q.front=(Q.front+1)%MAXQSIZE;
}

// 取队头元素
QElemType GetHead(SqQueue Q){
    if (Q.front!=Q.rear)
        return Q.base[Q.front];
}
链队(链式表示)
类型定义
#define MAXQSIZE 100  // 最大队列长度
typedef struct Qnode {
	QElemType data;
	struct Qnode *next;
}QNode, *QueuePtr;


typedef struct LinkQueue{
    QueuePtr front; // 队头指针
    QueuePtr rear; // 队尾指针
}LinkQueue;
链队指针变化情况

在这里插入图片描述

链队的基本操作
// 链队列的初始化
Status InitQueue(LinkQueue &Q){
    Q.front=Q.rear=(QueuePtr)malloc(sizeof(Qnode));
    if(!Q.front) exit(OVERFLOW);
    Q.front->next=NULL;
    return OK;
}

//链队列的销毁(从头结点开始,依次释放所有节点)
Status DestroyQueue(LinkQueue &Q){
    While(Q.front){
        p=Q.front->next; free(Q.front); Q.front=p; // 使用临时指针p
        // Q.rear=Q.front->next; free(Q.front);Q.front=Q.rear; 使用没有存在感的rear指针,闲着也是闲着
    }
    return OK;
}

// 链队列的入队
Status EnQueue(LinkQueue &Q, QElemType e){
    p=(QueuePtr)malloc(sizeof(QNode)); //分配新节点
    if(!p) exit(OVERFLOW); // 好习惯判断是否分配失败
    p->data=e; p->next=NULL; // 新节点赋值,next置空
    Q.rear->next=p; // 原尾结点指向新节点 
    Q.rear=p; //尾指针移动
    return OK;
}

// 链队列的出队
Status DeQueue(LinkQueue &Q, QElemType &e){
    if (Q.front == Q.rear) return ERROR;
    e=Q.front->data;
    p=Q.front->next; // 临时指针p
    Q.front->next=p->next; // 头指针指向下下一个节点
    if (Q.rear==p) Q.rear=Q.front; // 如果删除的节点刚好是尾结点,那么删除后尾指针也需要指向头结点,不然就孤家寡人了
    delete p;
    return OK;
}

// 求链队的队头元素
Status GetHead(LinkQueue Q, QElemType &e){
    if (Q.front==Q.rear) return ERROR;
    return Q.front->next->data;
    return OK;
}

TO BE CONTINUED…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/608199.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于Python的接口自动化-JSON模块的操作

目录 引言 一、JSON是啥&#xff1f; 二、JSON的有效数据类型 三、Python JSON库的使用 结语 引言 在使用Python进行接口自动化测试脚本时&#xff0c;一般都是脚本只写接口测试逻辑实现&#xff0c;而执行脚本时需要的测试用例数据都是写入excel、数据库或者指定的配置文…

入门编程指南:如何从零开始学习编程?

一、自学编程需要注意什么&#xff1f; 自学编程需要注意以下几点&#xff1a; 选择适合自己的编程语言&#xff0c;在学习初期建议选择易入手的编程语言。需要不断地练习&#xff0c;并建立自己的编程项目&#xff0c;以此提高编程技巧和应用能力。追求知识的全面性&#xf…

实验二十二、压控电压源二阶带通滤波器的参数选择

一、题目 如图1所示电路中&#xff0c;已知 R 51 k Ω R51\,\textrm kΩ R51kΩ&#xff0c; R 3 20 k Ω R_320\,\textrm kΩ R3​20kΩ&#xff1b; f 0 1 kHz f_01\,\textrm{kHz} f0​1kHz。利用 Multisim 分析下列问题&#xff1a; &#xff08;1&#xff09;选取合适…

[图表]pyecharts-K线图

[图表]pyecharts-K线图 先来看代码&#xff1a; import requests from typing import List, Unionfrom pyecharts import options as opts from pyecharts.charts import Kline, Line, Bar, Griddef get_data():response requests.get(url"https://echarts.apache.org/…

攻击者使用 Python 编译的字节码来逃避检测

以 PyPI&#xff08;Python 包索引&#xff09;等开源包存储库为目标的攻击者设计了一种新技术&#xff0c;可以将他们的恶意代码隐藏在安全扫描器、人工审查和其他形式的安全分析中。 在一次事件中&#xff0c;研究人员发现恶意软件代码隐藏在 Python 字节码 (PYC) 文件中&am…

Scala学习(十二)---模式匹配

文章目录 1.基本语法2.模式守卫3.匹配常量和类型4.匹配对象和样例类4.1 匹配对象4.2 匹配样例类 5.偏函数中的模式匹配 1.基本语法 在Scala中的模式匹配类似于Java中的switch语法 //模式匹配基本语法val a10val b20val c""c match {case "" >println(…

VScode远程连接虚拟机(ubuntu系统)

文章目录 1. Windows端安装VScode2. 安装远程登录插件3. 配置Remote-SSH插件关于关闭后如何打开该配置文件 4. 测试ubuntu与windows可否ping通5. 在Ubuntu中安装 SSH1.检查是否安装ssh-server2.安装openssh-server3.查看ssh服务是否启动4.Ubuntu中配置openssh-server开机自动启…

路径规划算法:基于蝠鲼觅食优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于蝠鲼觅食优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于蝠鲼觅食优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

6.4下周黄金最新行情走势分析及开盘交易策略

近期有哪些消息面影响黄金走势&#xff1f;下周黄金多空该如何研判&#xff1f; ​黄金消息面解析&#xff1a;周五(6月2日)&#xff0c;美市尾盘&#xff0c;现货黄金收报1947.82美元/盎司&#xff0c;大幅下跌29.70美元或1.50%&#xff0c;日内最高触及1983.43美元/盎司&…

chatgpt赋能python:Python升序排序

Python升序排序 Python是一种非常强大的编程语言&#xff0c;它在数学计算、数据处理等方面具备很强的优势。在实际应用中&#xff0c;我们经常需要对一系列数据进行排序。而在Python中&#xff0c;升序排序是非常常见的操作。本篇文章将介绍在Python中如何使用ifelse进行升序…

JavaWeb13(ajax01 AJAX介绍AJAX登陆AJAX加入购物车AJAX修改购物车商品数量)

目录 一. 什么是ajax 二.为什么需要AJAX? 三. 同步和异步的区别. 四.基于jQuery实现AJAX语法 4.1 语法1-$.ajax(url,[settings]). 4.1 语法2-$.get/post(url, [data], [callback], [type]). 五 .案例 5.1 ajax实现登录 ①html代码 用户登录 用户名&#xff1a; 密码…

【无功优化】基于改进教与学算法的配电网无功优化【IEEE33节点】(Matlab代码时候)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

揭秘照片修复技巧:手把手教你如何让模糊照片变清晰

作为一名修图小能手&#xff0c;行走于修图界&#xff0c;修复模糊的照片是必备的技能之一&#xff0c;最近收到很多粉丝的私信&#xff0c;清一色都是问的怎么免费把照片变清晰&#xff0c;为了给各位小伙伴们解决难题&#xff0c;我决定拿出我私藏多年的秘密武器&#xff0c;…

【CloudCompare教程】016:计算点云的法向量

本文讲解CloudCompare计算点云的法向量的方法。 文章目录 一、法向量概述二、法向量计算1. 平面法向量2. 二次曲面3.三角网格化一、法向量概述 法向量,是空间解析几何的一个概念,垂直于平面的直线所表示的向量为该平面的法向量。法向量适用于解析几何。由于空间内有无数个直…

HAL库记录-RTC

芯片:STM32F29IIGT6 阿波罗开发板 1.配置时钟 2.HAL外设配置 3.代码解析 生成rtc文件 RTC_HandleTypeDef hrtc;/* RTC init function */ void MX_RTC_Init(void) {/* USER CODE BEGIN RTC_Init 0 */RTC_TimeTypeDef rtc_time;RTC_DateTypeDef rtc_data;/* USER CODE END RTC…

node笔记_生成自定义目录文件

文章目录 ⭐前言⭐node生成目录&#x1f496; mkdirSync创建目录&#x1f496; stat判断目录是否存在&#x1f496; mkdir创建目录&#x1f496; 动态创建目录文件 ⭐结束 ⭐前言 大家好&#xff01;我是yma16&#xff0c;本文分享node生成自定义目录文件。 背景&#xff1a; …

chatgpt赋能python:Python中去掉数字末尾的0:一种简单有效的方法

Python中去掉数字末尾的0&#xff1a;一种简单有效的方法 Python作为一种流行的编程语言&#xff0c;经常被用于各种应用程序的编写。在这篇文章中&#xff0c;我们将介绍如何使用Python去掉数字末尾的零的一种简单有效的方法。 为什么要去掉数字末尾的0&#xff1f; 对于数…

【工具使用】STM32CubeMX-GPIO配置

一、概述 无论是新手还是大佬&#xff0c;基于STM32单片机的开发&#xff0c;使用STM32CubeMX都是可以极大提升开发效率的&#xff0c;并且其界面化的开发&#xff0c;也大大降低了新手对STM32单片机的开发门槛。     本文主要讲述STM32芯片的GPIO的配置及其相关知识。GPIO…

(转载)基本粒子群算法及惯性权重分析(matlab实现)

1 理论基础 粒子群算法(particle swarm optimization,PSO)是计算智能领域&#xff0c;除了蚁群算法、鱼群算法之外的一种群体智能的优化算法。该算法最早由Kennedy和Eberhart在1995年提出的。PSO算法源于对鸟类捕食行为的研究&#xff0c;鸟类捕食时&#xff0c;找到食物最简单…

一零五九、Windows系统(amd)通过VMware安装黑苹果

我来详细的说一下过程&#xff1a; 配置&#xff1a; windows amd锐龙VMware 16.0 &#xff08;16.1.0 build-17198959&#xff09;macos 11.1unlocker(工具&#xff0c;让虚拟机支持引导苹果系统) 总体步骤&#xff1a; 下载iso镜像和unlocker工具,这里提供两个链接&#…