3.6 排序算法
3.6.1 直接插入排序
●具体做法是:在插入第i个记录时,R1,R2,.....,Ri-1已经排好序,将记录Ri的关键字ki依次与关键字ki-1, ki-2,....,k1进行比较,从而找到Ri应该插入的位置,插入位置及其后的记录依次向后移动。
3.6.2 冒泡排序
首先将第一个记录的关 键字和第二个记录的关键字进行比较,若为逆序,则交换两个记录的值,然后比较第二个记录和第三个记录的关键字,依此类推。
3.6.3 简单选择排序
n个记录进行简单选择排序的基本方法是:
通过n-i次关键字之间的比较,从n-i+1个记录中选出关键字最小的记录,并和第i (1≤i≤n) 个记录进行交换,当i等于n时所有记录有序排列。
3.6.4 希尔排序
希尔排序又称“缩小增量排序”,是对直接插入排序方法的改进。
先将整个待排记录序列分割成若干子序列,然后分别进行直接插入排序,待整个序列中的记录基本有序时,再对全体记录进行一次直接插入排序。
解释:如图,当d=5时,48和间隔为‘5’的12比较后互换位置(12<48),37和间隔为’5‘的26比较后互换位置,以此类推;然后令d=3,重复类似上述的操作,最后令d=1,相邻比较得到最终结果。
3.6.5 快速排序
过于复杂,考试有个印象就行,有兴趣可看
3.6.6 堆排序
堆:对于n个元素的关键字序列{k1, k2,....,kn},当且仅当满足下列关系时称其为堆。
基本思想:对一组待排序记录的关键字,首先把它们按堆的定义排成一个序列(即建立初始堆),从而输出堆顶的最小关键字(对于小顶堆而言)。然后将剩余的关键字再调整成新堆,便得到次小的关键字,如此反复,直到全部关键字排成有序序列为止。
3.6.7 归并排序
基本思想:把一个有n个记录的无序文件看成是由n个长度为1的有序子文件组成的文件,然后进行两两归并,得到n /2个长度为2或1的有序文件,再两两归并,如此重复,直至最后形成包含n个记录的有序文件为止。
3.6.8 总结
1、直接插入排序:按顺序插入待排关键字,插入时依次查找位置,直接插入,后面的依次后移。
2、冒泡排序:依次把相邻的两个记录进行比较,然后交换位置。
3、简单选择排序:每次选择最小的,与第一个没有排过序的记录交换。
4、希尔排序:间隔若干个空的记录分为一组,进行直接插入排序,依次将间隔缩小到1为止。
5、快速排序:设两个指针指示头尾,从尾开始,首尾交替轮流和枢。记录(第一个记录)进行比较,并交换位置。
6、堆排序:反复将待排序列建立成堆,并取堆顶。
7、归并排序:两两归并为一组,再四个记录归并为一组,依此类推。
***********************************************************************************************************
3.7 查找算法
3.7.1 查找表及查找效率
查找表定义:是指由同一类型的数据元素(或记录)构成的集合。
静态查找表:只进行“查询"和“检索”操作。
动态查找表:除了查询和检索外可能还会进行插入和删除操作。
关键字:是数据元素(或记录)的某个数据项的值,用它来识别(标识)这个数据元素(或记录)。
查找:根据给定的某个值,在查找表中确定是否存在一个其关键字等于给定值的记录或数据元素。
平均查找长度(ASL):对于查找算法来说,其基本操作是“将记录的关键字与给定值进行比较”。因此,通常以“其关键字和给定值进行比较的记录个数的平均值”作为衡量查找算法好坏的依据。
3.7.2 顺序查找
从表中的一端开始,逐个进行记录的关键字和给定值的比较,若找到一个记录的关键字与给定值相等,则查找成功;若整个表中的记录均比较过,仍未找到关键字等于给定值的记录,则查找失败。
查找效率低,但是算法简单且适应面广。
3.7.3 折半查找(二分查找)
基本思想:先令查找表中间位置记录的关键字和给定值比较,若相等,则查找成功;若不等,则缩小范围,直至新的查找区间中间位置记录的关键字等于给定值或者查找区间没有元素时(查找不成功)为止。
这种方法要求查找表进行顺序存储并且按关键字有序排列。
查找效率比顺序查找要高,但要求关键字有序排列。
适用于表不易变动,且又经常进行查找的情况。
折半查找断定树
从折半查找的过程来看,可以用一棵二叉树来描述。通常称这个描述折半查找二叉树的过程称为折半查找判定树。
3.7.4 树表查找
二叉查找树是一种动态查找表,表结构本身是在查找过程中动态生成的。
设关键字序列为{46,25,54,13,29,91}
3.7.5 索引顺序查找
是对顺序查找的一种改进。
将表分成若干块,每一块中的关键字不一定有序,但块之间是有序的。即后一块中所有记录的关键字均大于前一个块中最大的关键字。此外,还建立了一个“索引表”,索引表按关键字有序。
因此,查找过程分为两步:第一步在索引表中确定待查记录所在的块;第二步在块内顺序查找。
进行分块查找时可将长度为n的表均匀地分成b块,每块含有s个记录,即b=[n/s]([取整])。在等概率的情况下,块内查找的概率为1/s,每块的查找概率为1/b,若用顺序查找方法确定元素所在的块,则分块查找的平均查找长度为:
可见,其平均查找长度在这种条件下不仅与表长n有关,而且和每一块中的记录数s有关。可以证明,当s取√n时,ASLbs 取最小值√n+1,这时的查找效率较顺序查找要好得多,但远不及折半查找。
3.7.6 哈希查找
前面几种查找方法中,记录的存储位置和关键码之间不存在确定的关系,因此查找时都要建立在对关键字进行比较的基础之上。
哈希函数:关键字作为自变量,关键字存放的地址作为因变量。
Hi=Hash (Key)
这一映射过程称为哈希造表或散列,所得的存储位置称为哈希地址或散列地址。
冲突:对于某个哈希函数Hash和两个关键字K1和K2,如果K1≠K2而Hash (K1) =Hash (K2),则称出现了冲突。
采用哈希法主要考虑的两个问题是哈希函数的构造和冲突的解决。
冲突的处理:
(1)开放定址法:
其中,Hash (key)为哈希函数,m为哈希表的表长,di为增量序列。
常见的增量序列有如下三种:
di=1, 2, 3, ....,m-1,称为线性探测再散列。
di=1的平方, -(1的平方), 2的平方, -(2的平方).....正负k的平方 (k≤m/2), 称为二次探测再散列。
di=伪随机序列,称为随机探测再散列。
举例:例:设关键码序列为47, 34, 19, 12, 52, 38, 33, 57, 63, 21,哈希表表长为13,哈希函数为Hash(key) =key mod 11,用线性探测法解决冲突构造哈希表。
47mod11=3,47放在地址为3;34mod11=1.....12mod11也等于1,地址为1已被占用,如果用线性探测法的话,12这个数往后找,直到找到空位并放在那里,后面的同理这样操作。
如果用二次探测再散列,如果某个数的位置被占,先看这个位置+1,然后是-1,然后是+4,-4....(正负k的平方),直到找到空位放下。
(2)链地址法:
它将具有相同哈希函数值的记录组织成一个链表,当链域的值为NULL时,表示已没有后继记录。
地址里存放的是指针,而不是关键字,将哈希函数值相同的记录组成一个链表。
举例:哈希表表长为11, 哈希函数为hash (key)=key mod 11, 对于关键码序列为47,34,12,52,38,33,27,3,使用链地址法构造哈希表。
相较于开放定址法,链地址法不用担心哈希地址出现重复。如果出现重复,则用链表的形式存储下来。