数 据 结 构 | 数据逻辑结构 | 集合 | (无逻辑结构) | |
线性结构 | 一般线性表 | 线性表 | ||
特殊线性表 | 栈 | |||
队列 | ||||
字符串 | ||||
线性表的推广 | 数组 | |||
广义表 | ||||
非线性结构 | 树结构 | 树 | ||
二叉树 | ||||
图结构 | 有向图 | |||
无向图 | ||||
集合结构 | ||||
存储结构 |
数据结构 | 逻辑结构 | 集合 | (无逻辑结构) |
线性结构 | 一维数组 | ||
队列 | |||
栈 | |||
非线性结构 | 树 | ||
图 | |||
多维数组 | |||
存储结构 | 顺序存储结构 | ||
链式存储结构 | |||
索性存储结构 | |||
散列存储结构 | |||
- 线性结构
线性表
定义:由n(n>=0)数据特性相同的元素构成的有限序列。(当n=0时称为空表)
特点:
1.存在唯一一个被称作“第一个”的数据元素。
- 存在唯一一个被称作“最后一个”的数据元素。
- 除第一个之外,结构中的每个数据元素只有一个前驱。
- 除最后一个之外,结构中的每个数据元素只有一个后继。
队列
和栈相反是一种先进先出的线性表(一端插入另一端删除)允许插入称为队尾允许删除一端称为队头。
栈
定义:是限定仅在表尾进行插入和删除操作的线性表。(所以表尾对其有特殊含义称为栈顶top表头称为栈底bottom)。不含元素称为空栈,后进先出。
串(字符串)
定义:由零个或多个字符组成的有限序列。(数目n称为常数,0个字符称为空串)。
串中任意的连续字符组成的子序列称为该串的子串包含子串的串称为主串。通常称字符在蓄力中的序号为该字符在字符串中的位置。
两种基本的存储结构顺序存储和链式存储(多采用顺序存储结构)
数组
定义:由类型相同的数据元素构成的有序集合。
广义表
定义:线性表的推广也称为列表。(广义表的元素可以是子表,子表的元素也可以是子表)。结构相对灵活可兼容线性表、数组、树和有向图等各种常用数据结构。
通常采用链式存储结构。
树(Tree)
定义:n(n>=0)个节点的有限集。
树的存储结构:双亲表示法、孩子表示法、孩子兄弟表示法。
二叉树(Binary Tree)
定义:n(n>=0)个节点构成的有限集。
特点:
- 有且只有一个称之为根的节点
- 除根节点以外其余节点分为两个互不相交的子集T1、T2分别称为左子集和右子集且其都为二叉树。
树与二叉树的主要区别:
1二叉树每个节点最多只有两颗子树
2二叉树子树有左右之分,其次序不能随意颠倒。
二叉树的存储结构:顺序存储结构和链式存储结构.
图(Graoph)
定义:由V和E组成。
查找
查找表:是由同一类型的数据元素(或记录)构成的集合。
关键字:是数据元素中某个数据项的值,用它可以标识一个数据元素(或记录)关键字的主关键字(唯一标识一个记录)和关键字的次关键字(识别若干记录)。
查找:是指根据给定的某值,在查找表中确定一个关键字等于给定值的记录或数据元素。若表中存在这样一个记录则查找成功反正则查找不成功。
动态查找表和静态查找表:若在查找同时对表进行修改操作(插入or删除)称为动态查找表否则称为静态查找表。
平均查找长度:为确定记录在查找表中的位置,需和给定值进行比较的关键字个数的期望值,称为查找算法在查找成功时的平均查找长度。
线性表的查找 | 顺序查找 |
折半查找 | |
分块查找 |
顺序查找
过程:从表的一端开始,一次将记录的关键字和给定的值进行比较,若某个记录关键字和给定值相等则查找成功,反之扫描整个标后仍未找到则查找不成功。
顺序查找方法即适合线性表的顺序存储结构又适合线性表的链式存储结构。
折半查找(二分查找)
过程:从表的中间记录开始,如果给定值和中间记录的关键字相等,则查找成功,如果给定值大于或小于中间记录的关键字,则在表中大于或小于中间记录的那一半中查找,这样重复操作直到查找成功,或者在某一步中查找区间为空,则代表查找失败。
折半查找每一次查找比较都使查找范围缩小一半,与顺序查找相比,显然提高了效率。
要求线性表必须是顺序存储结构。
分块查找(索引顺序查找)
过程:建立索引表,子表建立索引项包含关键字项(其值为该子表内最大关键字)和指针(指示该子表的第一个记录在表中位置)索引表按关键字有序则表或者有序或者分块有序,查找过程分两步进行先确定待查记录所在子表然后在块中顺序查找。
由于由索引项组成的索引表按关键字有序,则确定块的查找可以用顺序查找亦可用折半查找,而若块中记录任意排列则在块中只能用顺序查找。
性能介于顺序查找和折半查找之间,由顺序查找和折半查找简单合成。
树表的查找 | 二叉排序树 |
平衡二叉树 | |
B-树 | |
B+树 |
二叉排序树(二叉查找树)
定义:二叉排序树或者一颗空树,或者是具有下列性质的树:
1、若她的左子树不空,则左子树所有的结点值均小于根节点值
2、若她的右子树不空,则右子树所有的结点值均大于根节点值
3、她的左子树和右子树分别也为二叉排序树。
查找:可以将其看成一个有序表,所以在二叉树上进行查找和折半查找类似同为逐步缩小查找范围。
基本概念和排序方法的概述
定义:排序是关键字的非递减或非递增顺序对一组记录重新排列(一组杂乱无序的数据按一定规律排列起来)
稳定性:当关键字都不相同时,则该无序序列排序后得到结构唯一。若有两个或两个以上关键字相同时,则所得到的的记录结果不唯一。若经过排序这些排序的相对次序不变,即 在原序列中,ri=rj,且ri在rj之前,而在排序后的序列中,ri仍在rj之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:指的是待排序记录全部存放在计算机内存中进行排序的过程。
外部排序:指的是排序记录数量很大以至于内存不能全部容纳在排序过程中尚需外存进行排序的排序过程。
内部排序方法分类:
插入类:将无序子序中的一个或几个记录插入到有序序列中从而增加有序子序的长度。主要包括直接插入排序、折半排序和希尔排序。
交换类:通过“交换”无序序列中的记录从而得到关键字最小或最大的记录,并将它加入有序子序以此方法增加记录的有序子序列长度主要包括冒泡排序和快速排序。
选择类:通过“选择”无序序列中的记录从而得到关键字最小或最大的记录,并将它加入有序子序以此方法增加记录的有序子序列长度主要包括简单选择排序、树形选择排序和堆排序。
归并类:通过“归并”两个或两个以上的记录有序子序列,逐步增加记录有序序列的长度。最常见的归并排序方法2-路归并排序。
分配类:是唯一一类不需要进行关键字之间比较的排序方法,排序事主要利用分配和收集两种基本操作来完成。分配类排序方法基数排序。
待排序记录的存储方式:
顺序表:记录之间的次序关系由其存储位置决定,实现排序需要移动记录。
链表:记录之间的关系由指针指示,实现排序不需要移动记录,仅需要修改指针就可以了这种排序方式称为链表排序。
地址排序:
待排序记录本身存储在一组地址连续的存储单元,同时另外设立一个指示各个记录存储位置的地址向量。在排序过程中不移动记录本身,而是移动地址向量中这些记录的地址在排序结束后在按照地址向量中的值调整记录所在位置。
判断算法好坏标准:(1)执行时间(2)辅助空间
插入排序:
1、直接插入排序
(1)冒泡排序
冒泡排序就是把小的元素往前调或者把大的元素往后调。比较是相邻的两个元素比较,交换也发生在这两个元素之间。所以,如果两个元素相等,我想你是不会再无聊地把他们俩交换一下的;如果两个相等的元素没有相邻,那么即使通过前面的两两交换把两个相邻起来,这时候也不会交换,所以相同元素的前后顺序并没有改 变,所以冒泡排序是一种稳定排序算法。
(2)选择排序
选择排序是给每个位置选择当前元素最小的,比如给第一个位置选择最小的,在剩余元素里面给第二个元素选择第二小的,依次类推,直到第n-1个元素,第n个 元素不用选择了,因为只剩下它一个最大的元素了。那么,在一趟选择,如果当前元素比一个元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么 交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5 2 9, 我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了,所以选择排序不是一个稳定的排序算法。
(3)插入排序
插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。当然,刚开始这个有序的小序列只有1个元素,就是第一个元素。比较是从有序序列的末尾开 始,也就是想要插入的元素和已经有序的最大者开始比起,如果比它大则直接插入在其后面,否则一直往前找直到找到它该插入的位置。如果碰见一个和插入元素相 等的,那么插入元素把想插入的元素放在相等元素的后面。所以,相等元素的前后顺序没有改变,从原无序序列出去的顺序就是排好序后的顺序,所以插入排序是稳 定的。
(4)快速排序
快速排序有两个方向,左边的i下标一直往右走,当a[i] <= a[center_index],其中center_index是中枢元素的数组下标,一般取为数组第0个元素。而右边的j下标一直往左走,当a[j] > a[center_index]。如果i和j都走不动了,i <= j, 交换a[i]和a[j],重复上面的过程,直到i>j。 交换a[j]和a[center_index],完成一趟快速排序。在中枢元素和a[j]交换的时候,很有可能把前面的元素的稳定性打乱,比如序列为 5 3 3 4 3 8 9 10 11, 现在中枢元素5和3(第5个元素,下标从1开始计)交换就会把元素3的稳定性打乱,所以快速排序是一个不稳定的排序算法,不稳定发生在中枢元素和a[j] 交换的时刻。
(5)归并排序
归并排序是把序列递归地分成短序列,递归出口是短序列只有1个元素(认为直接有序)或者2个元素(1次比较和交换),然后把各个有序的段序列合并成一个有 序的长序列,不断合并直到原序列全部排好序。可以发现,在1个或2个元素时,1个元素不会交换,2个元素如果大小相等也没有人故意交换,这不会破坏稳定 性。那么,在短的有序序列合并的过程中,稳定是否受到破坏?没有,合并过程中我们可以保证如果两个当前元素相等时,我们把处在前面的序列的元素保存在结 果序列的前面,这样就保证了稳定性。所以,归并排序也是稳定的排序算法。
(6)基数排序
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优 先级排序,最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。基数排序基于分别排序,分别收集,所以其是稳定的排序算法。
(7)希尔排序(shell)
希尔排序是按照不同步长对元素进行插入排序,当刚开始元素很无序的时候,步长最大,所以插入排序的元素个数很少,速度很快;当元素基本有序了,步长很小, 插入排序对于有序的序列效率很高。所以,希尔排序的时间复杂度会比o(n^2)好一些。由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元 素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。
(8)堆排序
我们知道堆的结构是节点i的孩子为2*i和2*i+1节点,大顶堆要求父节点大于等于其2个子节点,小顶堆要求父节点小于等于其2个子节点。在一个长为n 的序列,堆排序的过程是从第n/2开始和其子节点共3个值选择最大(大顶堆)或者最小(小顶堆),这3个元素之间的选择当然不会破坏稳定性。但当为n /2-1, n/2-2, ...1这些个父节点选择元素时,就会破坏稳定性。有可能第n/2个父节点交换把后面一个元素交换过去了,而第n/2-1个父节点把后面一个相同的元素没 有交换,那么这2个相同的元素之间的稳定性就被破坏了。所以,堆排序不是稳定的排序算法。
综上,得出结论: 选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法。