【软件设计师06】数据结构与算法基础

数据结构与算法基础

考点:数组与矩阵、线性表、广义表、树与二叉树、图、排序与查找算法基础与常见的算法

1. 数组

数组类型存储地址计算
一维度数组a[n]a[i]的存储地址为a+i*len
二维数组a[m][n]a[i][j]的存储地址;按行存储:a+(i*n+j)*len;按列存储:a+(j*m+i)*len

2. 稀疏矩阵

采用上三角或者下三角的形式存储矩阵

例题:A、可以使用代入法判断
在这里插入图片描述

3. 数据结构的定义

存储和组织数据的方式

线性结构、非线性结构包含树(不存在环路)和图(存在环路);从意义上讲图可以包含树,树包含线性结构

4. 线性表的定义 - 顺序表/链表

在这里插入图片描述
基本操作
单链表删除:p -> next = q -> next
单链表插入:s -> next = p -> next; p -> next = s;
在这里插入图片描述

5. 顺序存储与链式存储对比

性能类别具体项目顺序存储链式存储
空间性能存储密度=1, 更优<1
容量分配事先确定动态改变, 更优
时间性能查找运算O(n/2)O(n/2)
读运算O(1), 更优O([n+1]/2), 最好1, 最坏n
插入运算O(n/2), 最好0, 最坏nO(1), 更优
删除运算O({n-1}/2)O(1), 更优
## 6. 队列与栈

循环队列问题:无法区分队空和队满的情况
两种解决方案:1记录队满队空状态;2少存一位元素(多数)
在这里插入图片描述

例题:

在这里插入图片描述

7. 广义表

在这里插入图片描述

例一:3,2
例二:head(head(tail(LS1)))

8. 树与二叉树

基本概念:

结点的度是它的孩子字结点数,1结点度2,3结点度1,7结点度0

树的度是所有结点度中最高的结点的度;树的度为2

叶子结点是没有子结点的;4,5,7,8

分支节点,度不为0的节点

内部节点,即不是叶子结点,也不是根结点;2,3,6

父结点和子结点是相对的概念;2是1的子结点;4是2的子结点

兄弟结点;4和5

层次,4层

在这里插入图片描述

9. 满二叉树和完全二叉树

满二叉树:可以构成一个完整的三角形

完全二叉树:完全二叉树的定义是一个深度为k的有n个节点的二叉树,对树中的节点按从上至下、从左到右的顺序进行编号,编号1≤i≤n的结点与满二叉树中编号为i的结点在二叉树中的位置相同。

在这里插入图片描述

10. 二叉树的特性

二叉树的第i层最多有2^(i-1)个结点

深度为k的二叉树最多有2^k - 1个结点

对任何一颗二叉树,如果叶子结点数为n0,度为2的结点数为n2,则n0=n2+1

如果对一颗有n个结点的完全二叉树按层序编号,对任意结点i(1<=i<=n),有:
如果i=1,则结点无父结点,是二叉树的根,如果i>i,则它的父结点是i/2
如果2i>n,则结点为i为叶子结点,无左子结点;否则,其左子结点是2i
如果2i+1>n,则结点i无右叶子结点,否则,其右子结点是2i+1

11. 二叉树遍历

在这里插入图片描述

层次遍历:从根结点开始,每层依次从左至右访问完;12345678

前序遍历(根左右)是先访问根结点,再访问左子结点和右子结点;12457836

中序遍历(左根右)是先访问左子结点,在访问根结点和右子结点;42785136

后序遍历(左右根)是先访问左子结点,再访问右子结点和根结点;48752631

12. 反向构造二叉树

根据二叉树的遍历序列,反向构造二叉树;必须有中序序列和任意前序或后序序列才能实现

标记根结点,然后推理左右结点

在这里插入图片描述
在这里插入图片描述

13. 树转二叉树

孩子结点 - 左子树结点

兄弟结点 - 右孩子结点

在这里插入图片描述

14. 查找二叉树(二叉排序树)

也称二叉排序树;左子结点小于根;右子结点大于根;

在这里插入图片描述

插入结点:

若该键值结点已存在,则不再插入,如48
若查找二叉树为空树,则以新结点为查找二叉树
将要插入结点键值与插入后父结点键值比较,就能确定新结点是父结点的左子结点还是右子结点

删除结点:

若删除结点是叶子结点,则直接删除
若待删除结点只有一个子结点,则将这个子结点与待删除结点的父结点直接连接,如56
若待删除的结点p右两个子结点,则在其左子树上,用中序遍历寻找关键值最大的结点S,用结点s的值代替结点p的值,然后删除结点s,结点s必属于上述两种情况之一,如89

15. 最优二叉树(哈夫曼树)

树的路径长度:树的路径累加长度
权:某个叶子结点的键值,即某个字符出现的频度
带权路径长度:路径长度 * 权值;例如2结点,2*2=4;4结点3*4=12
树的带权路径长度(树的代价):所有叶子节点的带权路径长度之和

构造哈夫曼树是尝试让树的带权路径长度最小;如下第一种树的带权路径长度是41,第二种是25

在这里插入图片描述

例题:

1、从序列中选出2个权值最小的数 3,5构成一颗小树,小树的权是8,将8添加到序列

2、再从序列中选2个权值最小的7,8构成一颗树,得到权值15的树加到序列

3、依此类推不断构成树

4、求树的叶子结点带权路径长度只和得到树的带权路径长度

通过构造发现我们最开始的序列都是叶子结点,所以回头看定义树的带权路径长度也就是所以叶子结点带权路径长度只和

在这里插入图片描述

16. 线索二叉树

如图在二叉树的基础上有虚线建线把结点连接起来;

因为在二叉树中许多结点是空闲状态,一些结点的左子树和右子树的指针是空的

按照前序遍历、中序遍历、后序遍历序列的顺序连接指针,就构成了相对应种类的线索二叉树

在这里插入图片描述

17. 平衡二叉树

结点平衡度 = 左子树深度 - 右子树深度

在这里插入图片描述

18. 图 - 基本概念

在这里插入图片描述

邻接矩阵

无向图的邻接矩阵全对角线为0(自己连接自己的点),沿对角线对称,所以存储时可以只存上三角或下三角

在这里插入图片描述

邻接表

在这里插入图片描述

图的遍历

在这里插入图片描述

19. 图 - 拓扑排序

在这里插入图片描述

20. 图的最小生成树

保留最小权值的边并能使图连贯;

树和图的区别,树没有环路;设树的结点n,边则n-1;

普里姆算法

例题:从一个任意结点出发,将这个结点定义为红点集,其他结点为蓝点集;找出从红点集中到蓝点集中最小的权

比如选A,找到权值最小的A -> B,连接后将B加入红点集

再次判断的时候就需要把红点集的A,B找到蓝点集中到最小权;依此类推

在这里插入图片描述

克鲁斯卡尔算法

设顶点树为n,依次选择出图中最短的n-1条边,且每次选择下一条边时要保证不形成环路

21. 算法的特性

有穷性:执行有穷步数之后结束

确定性:算法中每一条指令都必须有确切的含义,不能含糊不清

输入数量(>=0)

输出数量(>=1)

有效性:算法的每个步骤都能有效执行并能得到确定的结果。例如a=0,b/a就无效。

22. 算法的复杂度

时间复杂度(重点,下午设计题出现问程序的时间复杂度计算)、空间复杂度

在这里插入图片描述

23. 顺序查找

时间复杂度O(n)

在这里插入图片描述

24. 二分查找

时间复杂度(log以2为底n的对数)
在这里插入图片描述

在这里插入图片描述

25. 散列表

在数据存储时遵循一定的规则。
在这里插入图片描述

26. 排序算法总结**

(有时只在上午考,有时上下午都考)

排序的概念

稳定与不稳定排序(排序前后原有的相等两个数字的顺序是否改变,比如分数的排名先来后到等)、内排序(在内存进行)与外排序(涉及到外部存储空间)

在这里插入图片描述

27. 冒泡排序

https://www.runoob.com/w3cnote/bubble-sort.html

比较相邻的元素。如果第一个比第二个大,就交换他们两个。

对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。

针对所有的元素重复以上的步骤,除了最后一个。

持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。

img

28. 直接选择排序

首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。

再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。

重复第二步,直到所有元素均排序完毕。

img

29. 直接插入排序

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

img

30. 希尔排序(Shell)

希尔排序,也称递减增量排序算法,是插入排序的一种更高效的改进版本。但希尔排序是非稳定排序算法。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:

  • 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率;
  • 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位;

希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行依次直接插入排序。

算法步骤:

选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1;

按增量序列个数 k,对序列进行 k 趟排序;

每趟排序,根据对应的增量 ti,将待排序列分割成若干长度为 m 的子序列,分别对各子表进行直接插入排序。仅增量因子为 1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

img

在这里插入图片描述

31. 归并排序

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。对有多个有序序列进行排序,为了方便一般每次操作两个序列。

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

img

31. 快速排序

快速排序是一种常用的排序算法,也是一种基于交换排序的算法。它的基本思想是通过一趟排序将待排序序列分割成独立的两部分,其中一部分的所有元素都比另一部分小,然后再按此方法对这两部分分别进行快速排序,递归地进行,以达到整个序列有序的目的。

具体实现过程如下:

  1. 选定一个枢纽元素(pivot),一般可以选择待排序数组的第一个元素,也可以随机选择。这个枢纽元素可以将数组分为两部分,一部分的元素都小于等于枢纽元素,另一部分的元素都大于枢纽元素。
  2. 然后将小于等于枢纽元素的元素放到枢纽元素的左边,大于枢纽元素的元素放到枢纽元素的右边。这一步称为分区(partitioning)。
  3. 递归地对枢纽元素左右两部分分别进行上述步骤,直到所有子问题的规模都变得足够小,可以直接采用插入排序等其他算法进行排序。
  4. 合并所有已排序的子序列,得到最终的排序结果。

快速排序的时间复杂度为O(nlogn),其中n为待排序序列的长度。它是原地排序算法,因此不需要额外的空间,但是快速排序的实现依赖于递归,因此递归过程中需要使用栈空间。同时,由于快速排序是一种不稳定的排序算法,因此在需要保持排序前后元素相对位置关系的情况下需要进行特殊处理。

img

public class QuickSort {
    public static void sort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        quickSort(arr, 0, arr.length - 1);
    }

    private static void quickSort(int[] arr, int left, int right) {
        if (left >= right) {
            return;
        }
        int pivotIndex = partition(arr, left, right);
        quickSort(arr, left, pivotIndex - 1);
        quickSort(arr, pivotIndex + 1, right);
    }

    private static int partition(int[] arr, int left, int right) {
        int pivot = arr[left];
        int i = left + 1, j = right;
        while (i <= j) {
            while (i <= j && arr[i] < pivot) {
                i++;
            }
            while (i <= j && arr[j] >= pivot) {
                j--;
            }
            if (i < j) {
                swap(arr, i, j);
            }
        }
        swap(arr, left, j);
        return j;
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

小于基准的放左边,大于基准的放右边;通过外层while里的两个while判断左右两边数是否需要交换;递归对分好的左右两边序列做相同操作

32. 堆排序

在这里插入图片描述
在这里插入图片描述

初建大顶堆:

从最后一个非叶子结点开始调整,依次倒出第2个,3个…

5和它的两个子结8,0点比较,将最大值调整为根;

4和2,6比较后调整

3个8,7比较后调整;注意跟包含子结点的8交换后还有进一步调整,3,和5,0调整

最后调整到根结点1和8,6调整,1,8交换后继续对当前包含子结点的1和5,7调整,把7换上来后7刚刚不包含子结点,所以交换结束

在这里插入图片描述

建立堆后的排序:

取走堆顶,将二叉树的最后一个结点放到堆顶

然后对堆进行调整,同上面的初建堆方法把20根两个子结点比对…

在这里插入图片描述

public class HeapSort implements IArraySort {

    @Override
    public int[] sort(int[] sourceArray) throws Exception {
        // 对 arr 进行拷贝,不改变参数内容
        int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);

        int len = arr.length;

        buildMaxHeap(arr, len);

        for (int i = len - 1; i > 0; i--) {
          	// 将堆顶(最大值)与最后一个结点交换,然后长度减一从前面的结点开始再构建大顶堆
            swap(arr, 0, i);
            len--;
            heapify(arr, 0, len);
        }
        return arr;
    }

    private void buildMaxHeap(int[] arr, int len) {
        // len长度的线性表,最后一个元素的父结点序号为n/2,因此第一个大顶堆的子根在这里诞生
        for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
            heapify(arr, i, len);
        }
    }

    private void heapify(int[] arr, int i, int len) {
        // 从0开始,平衡二叉树中当前的左、右子结点
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        int largest = i;

        if (left < len && arr[left] > arr[largest]) {
            largest = left;
        }

        if (right < len && arr[right] > arr[largest]) {
            largest = right;
        }

        if (largest != i) {
            swap(arr, i, largest);
            heapify(arr, largest, len);
        }
    }

    private void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

}

33. 基数排序

(考察的比较少)

基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。由于整数也可以表达字符串(比如名字或日期)和特定格式的浮点数,所以基数排序也不是只能使用于整数。

先排个位,再排十位,再排百位…

在这里插入图片描述

img

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring原理学习(二):Bean的生命周期和Bean后处理器

〇、前言 倘若是为了面试&#xff0c;请背下来下面这段&#xff1a; spring的bean的生命周期主要是创建bean的过程&#xff0c;一个bean的生命周期主要是4个步骤&#xff1a;实例化、属性注入、初始化、销毁。但是对于一些复杂的bean的创建&#xff0c;spring会在bean的生命周期…

如何搭建chatGPT4.0模型-国内如何用chatGPT4.0

国内如何用chatGPT4.0 在国内&#xff0c;目前可以通过以下途径使用 OpenAI 的 ChatGPT 4.0&#xff1a; 自己搭建模型&#xff1a;如果您具备一定的技术能力&#xff0c;可以通过下载预训练模型和相关的开发工具包&#xff0c;自行搭建 ChatGPT 4.0 模型。OpenAI提供了相关的…

旅游心得Traveling Experience

前言 加油 原文 旅游心得常用会话 ❶ Share photos of the trip with friends. 与朋友分享旅游的照片。 ❷ We’ll go to the Great Wall, if you prefer. 你如果愿意的话,我们去长城。 ❸ Would you go to the church or the synagogue or the mosque? 你会去教堂,犹太…

二结(4.11)IO流学习

FIle类只能对文件本身操作&#xff0c;不能读写文件里面存储的数据 文件保存的位置叫路径&#xff0c;而数据传输叫IO流 Java I/O流&#xff08;Input/Output stream&#xff09;在Java应用程序中用于读取和写入数据&#xff0c;可分为基本流和高级流两类 关于什么是输出流、…

CSC中加学者交换项目申报即将开始

3月31日&#xff0c;国家留学基金委&#xff08;CSC&#xff09;发布了2023-2024年度中加学者交换项目遴选通知。根据通知精神&#xff0c;选派规模&#xff1a;100人月&#xff0c;留学及资助期限&#xff1a;4-12个月&#xff0c;网上报名及申请受理时间为2023年4月11日至6月…

SpringCloud学习6(Spring Cloud Alibaba)断路器Sentinel熔断降级

文章目录服务熔断降级Sentinel高并发请求模拟&#xff08;这里我们使用contiperf来进行测试&#xff09;修改tomcat配置最大线程数引入测试依赖编写测试代码服务雪崩服务雪崩的容错方案&#xff08;隔离、超时、限流、熔断、降级&#xff09;隔离机制&#xff1a;超时机制&…

Baumer工业相机堡盟工业相机如何设置网口的IP地址(工业相机连接的网口设置IP地址步骤)

Baumer工业相机堡盟工业相机如何设置网口的IP地址&#xff08;工业相机连接的网口设置IP地址步骤&#xff09;Baumer工业相机Baumer工业相机设置网络端口IP地址匹配设置网络端口IP地址和工业相机IP地址匹配第一次打开CameraExplorer软件确认问题为IP地址不匹配问题打开网络连接…

C++ - 继承 | 菱形继承

之前的文章中我们简要的讲述了C中继承部分的知识&#xff0c;但是还没有完全的讲完&#xff0c;在本文中将会讲到菱形继承的问题。 复杂的菱形继承 单继承&#xff1a;一个子类只有一个直接父类时称这个继承关系为单继承。 多继承&#xff1a;一个子类有两个或以上直接父类时…

最新阿里、腾讯、华为、字节等大厂的薪资和职级对比,看看你差了多少...

互联网大厂新入职员工各职级薪资对应表(技术线)~ 最新阿里、腾讯、华为、字节跳动等大厂的薪资和职级对比 上面的表格不排除有很极端的收入情况&#xff0c;但至少能囊括一部分同职级的收入。这个表是“技术线”新入职员工的职级和薪资情况&#xff0c;非技术线(如产品、运营、…

Android基础四大组件之Activity的启动过程源码解析

前言 Activity是Android中一个很重要的概念&#xff0c;堪称四大组件之首&#xff0c;关于Activity有很多内容&#xff0c;比如生命周期和启动Flags&#xff0c;这二者想要说清楚&#xff0c;恐怕又要写两篇长文&#xff0c;更何况分析它们的源码呢。不过本文的侧重点不是它们…

面试官:你可以用 for of 遍历 Object 吗?

本文以 用 for of遍历 Object 为引 来聊聊 迭代器模式。 什么是迭代器模式 迭代器模式提供一种方法顺序访问一个聚合对象中的各个元素&#xff0c;而又不暴露该对象的内部表示。 ——《设计模式&#xff1a;可复用面向对象软件的基础》 可以说迭代器模式就是为了遍历存在的。提…

HTML5 <body> 标签

HTML <body> 标签 实例 一个简单的 HTML 文档&#xff0c;包含尽可能少的必需的标签&#xff1a; <!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>文档标题</title> </head><body> 文档内容…

单例设计模式解读

目录 单例设计模式介绍 单例设计模式八种方式 饿汉式&#xff08;静态常量&#xff09; 饿汉式&#xff08;静态代码块&#xff09; 懒汉式(线程不安全) 懒汉式(线程安全&#xff0c;同步方法) 懒汉式(线程安全&#xff0c;同步代码块) 懒汉式(线程安全&#xff0c;同步…

libcurl库的安装及使用说明

目录 一 libcurl库安装 ① 下载网址 ② libcurl库安装步骤 ③ libcurl等第三方库的通用编译方法 二 调用libcurl编程访问百度主页 ① 代码说明 ② 编译说明 ③ 执行说明 三 libcurl的使用说明 ① curl相关函数简介 ② curl_easy_setopt函数部分选项介绍 ③…

【AUTOSAR】【Can通信】CanSM

目录 一、概述 二、限制说明 三、功能说明 3.1 基础需求 3.2 CAN网络的状态机 3.3 错误分类 3.3.1 开发错误 3.3.2 运行错误 3.3.3 拓展生产错误 3.4 ECU在线主动/被动模式 四、API接口 4.1 API定义 4.2 调度接口 一、概述 该文档描述了AUTOSAR基本软件模块CAN状态…

2023年第十四届蓝桥杯Java_大学B组真题

Java_B组试题 A: 阶乘求和试题 B: 幸运数字试题 C: 数组分割试题 D: 矩形总面积试题 E: 蜗牛试题 F: 合并区域试题 G: 买二赠一试题 H: 合并石子试题 I: 最大开支试题 J: 魔法阵【考生须知】 考试开始后&#xff0c;选手首先下载题目&#xff0c;并使用考场现场公布的解压密码解…

编译技术-词法理论

一、文法的种类 1.1 分类定义 Chomsky 文法定义&#xff1a; G(V,Vt,P,Z)G (V, V_t, P, Z)G(V,Vt​,P,Z)VVV&#xff1a;符号集合VtV_tVt​&#xff1a;终结符号集合PPP &#xff1a;有穷规则集合ZZZ&#xff1a;是被符号&#xff0c;不能是终结符 关于不同文法的区别 类型…

【多线程与高并发(锁)】1、锁的概念、分类和状态

1、锁的概念 java当中的锁、是在多线程环境下为保证共享资源健康、线程安全的一种手段。 线程操作某个共享资源之前&#xff0c;先对资源加一层锁&#xff0c;保证操作期间没有其他线程访问资源&#xff0c;当操作完成后&#xff0c;再释放锁。 2、锁的分类 Java中的锁按照…

ChatGPT对我们的影响-ChatGPT能给我们带来什么

ChatGPT日常应用 ChatGPT是一种应用广泛的自然语言处理算法&#xff0c;其可以应用于多种日常场景。以下是一些ChatGPT的日常应用&#xff1a; 聊天机器人&#xff1a;ChatGPT可用于构建聊天机器人&#xff0c;通过与用户进行自然语言交互来提供个性化的服务和支持。 新闻稿和…

MyBatis零基础入门实践

MyBatis一、MyBatis简介1、MyBatis历史2、MyBatis特性3、MyBatis下载4、和其它持久化层技术对比二、搭建MyBatis1、开发环境2、创建maven工程3、创建MyBatis的核心配置文件4、创建mapper接口5、创建MyBatis的映射文件6、通过junit测试功能7、加入log4j日志功能三、核心配置文件…