数据结构笔记归档3
图
1.图的基本概念
在线性表中,数据元素之间是被串起来的,仅有线性关系,每个数据元素只有一个直接前驱和一个直接后继。在树形结构中,数据元素之间有着明显的层次关系,并且每一层上的数据元素可能和下一层中多个元素相关,但只能和上一层中一个元素相关。图是一种较线性表和树更加复杂的数据结构。在图形结构中,结点之间的关系可以是任意的,图中任意两个数据元素之间都可能相关。
1.1.图的定义
图(Graph)是一种非线性结构,其中的元素是多对多的关系。
图(Graph)是由非空的顶点的集合和描述顶点关系即边的集合组成。
1.2.图的基本术语
- 有向图:边是有方向的图
- 无向图:边是无方向的图
2.图的存储结构
2.1.图的连接矩阵
1 |
|
2.2.图的连接表
1 |
|
3.图的遍历
3.1.广度优先搜索
1 | /* 邻接矩阵存储的图 - BFS */ |
3.2.深度优先搜索
1 | /* 邻接表存储的图 - DFS */ |
4.有向图连接矩阵
4.1.图的定义
1 |
|
4.2.创建图
1 | int CreateMatix(AdjMatix &g) |
4.3.列出图
1 | void DispMatix(AdjMatix g) |
4.4.main
1 | void main() |
5.有向图连接链表
5.1.图的定义
1 |
|
5.2.创建图
1 | int CreateAdjList(AdjList *&G) /*建立有向图的邻接表*/ |
5.3.列出图
1 | void DispAdjList(AdjList *G) |
5.4.main
1 | void main() |
6.图的基本运算(By-Go)
1 | // Package graph creates a ItemGraph data structure for the Item type |
7.图的遍历
给定一个图G=(V,E)和V(G)中的任一顶点v,从v出发,顺着G的边访问G中的所有顶点,且每个顶点仅被访问一次,这一过程称为遍历图。
一般设置一个辅助数组visited[],用来标记顶点是否被访问过,初始状态为0,访问过则设置为1。
7.1.广度优先遍历
1 |
|
7.2.深度优先遍历
- 从图G中某个顶点vi出发,访问vi,然后选择一个与vi相邻且没有被访问过的顶点v访问,再从v出发选择一个与v相邻且未被访问的顶点vj访问,依次访问。
- 如果当前已被访问的顶点的所有邻接顶点都已被访问,则回退到已被访问的顶点序列中最后一个拥有未被访问的相邻顶点w,从w出发按相同的方法继续遍历,直到所有的顶点都被访问到。
1 |
|
8.最小生成树
8.1.普利姆算法
1 |
|
8.2.克鲁斯卡尔算法
1 |
|
9.最短路径
9.1.狄克斯特拉算法
1 |
|
9.2.弗洛伊德算法
1 |
|
10.拓扑排序算法
1 |
|
查找
1.查找的基本概念
查找是在大量的信息中寻找一个特定的信息元素,在计算机应用中,查找是常用的基本运算,例如编译程序中符号表的查找。
1.1.查找的定义
根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
1.2.查找算法分类
- 静态查找和动态查找
注:静态或者动态都是针对查找表而言的。动态表指查找表中有删除和插入操作的表。
无序查找和有序查找
- 无序查找:被查找数列有序无序均可。
- 有序查找:被查找数列必须为有序数列。
平均查找长度(Average Search Length,ASL):需和指定key进行比较的关键字的个数的期望值,称为查找算法在查找成功时的平均查找长度。
对于含有n个数据元素的查找表,查找成功的平均查找长度为:ASL = Pi*Ci的和。
- Pi:查找表中第i个数据元素的概率。
- Ci:找到第i个数据元素时已经比较过的次数。
2.顺序查找
1 |
|
3.二分法查找
1 |
|
4.分块查找
1 |
|
5.二叉排序树查找
1 |
|
6.哈希表查找
6.1.By C++
1 |
|
6.2.By Golang
1 | // Package hashtable creates a ValueHashtable data structure for the Item type |
7.哈希查找
1 |
|
排序
1.排序的定义
对一序列对象根据某个关键字进行排序。
1.1.排序方法比较
排序方法 | 时间复杂度 | 空间 复杂度 | 稳定性 | 复杂性 | ||
---|---|---|---|---|---|---|
最坏情况 | 平均情况 | 最好情况 | ||||
直接插入排序 | O(n2) | O(n2) | O(n) | O(1) | 稳定 | 简单 |
希尔排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不稳定 | 较复杂 |
选择排序 | O(n2) | O(n2) | O(n2) | O(1) | 不稳定 | 简单 |
堆排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(1) | 不稳定 | 较复杂 |
冒泡排序 | O(n2) | O(n2) | O(n) | O(1) | 稳定 | 简单 |
快速排序 | O(nlog2n) | O(n2) | O(nlog2n) | O(nlog2n) | 不稳定 | 较复杂 |
归并排序 | O(nlog2n) | O(nlog2n) | O(nlog2n) | O(n) | 稳定 | 较复杂 |
基数排序 | O(d(n+r)) | O(d(n+r)) | O(d(n+r)) | O(n+r) | 稳定 | 较复杂 |
2.插入排序
2.1.直接插入排序
1 |
|
2.2.希尔排序
1 |
|
3.选择排序
3.1.直接选择排序
3.1.1.基本思想
- 每次从未排序的序列中选择最小的数放置在该未排序序列的第一个
- 不断循环,直到排序完成
3.1.2.步骤
- 第一层循环:i=0; i < len(list)-1; i++
- 第二层循环:j := i + 1; j < len(list); j++
- 寻找未排序序列中最小的数: if list[j] < list[minIndex] { minIndex = j }
- 将最小的数与放置到当前未排序序列的第一个: list[i], list[minIndex] = list[minIndex], list[i]
3.1.3.By C++
1 |
|
3.1.4.By Golang
1 | package main |
3.1.5.排序过程
1 | 初始序列: [75 87 68 92 88 61 77 96 80 72] |
3.2.堆排序
3.2.1.By C++
1 |
|
4.交换排序
4.1.冒泡排序
4.1.1.基本思想
- 比较相邻两个元素,如果第一个比第二个大,就交换两者的顺序
- 对每一对相邻的元素做同样的操作,从最后一对到第一对,每一趟结束最小的元素会排在第一个(即冒泡)
- 从未排序的元素开始循环做以上操作,直到排序完成
4.1.2.步骤
- 第一层循环: i=0; i<(len-1); i++
- 第二层循环: j=len-1; j>i; j–
- 比较相邻两个元素: list[j-1]和list[j]
- 如果前者比后者大,就交换顺序: list[j-1], list[j] = list[j], list[j-1]
4.1.3.By C++
1 |
|
4.1.4.By Golang
1 | package main |
4.1.5.排序过程
1 | 初始序列: [75 87 68 92 88 61 77 96 80 72] |
4.2.快速排序
4.2.1.基本思想
- 分治:在未排序序列中选择一个基准数(一般为第一个),将小于基准数的放在其左边,大于基准数的放在其右边,即分成两个区间
- 递归:将上述两个区间,每个区间内执行上述操作,以此类推,直到排序完成
4.2.2.步骤
- 选择一个基准数,一般为第一个: pivot := list[left]
- 将小于基准数的放在其左边
- 将大于基准数的放在其右边
- 对每个分区执行递归操作:quickSort(list, left, i-1);quickSort(list, i+1, right)
4.2.3.By C++
1 |
|
4.2.4.By Golang
1 | package main |
4.2.5.排序过程
1 | 初始序列: [75 87 68 92 88 61 77 96 80 72] |
5.归并排序
1 |
|
6.基数排序
1 |
|