排序和查找

待整理
选择排序---不断地选择剩余元素之中的最小者。

思想:
首先找到数组中最小的那个元素,其次将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。再次在剩下的元素中,找到最小的元素,将它与数组的第二个元素交换位置。如此重复,直到将整个数组排序。
比较次数:
对于长度为N的数组,选择排序需要大约(N^2)/2次比较和N次交换。
特点:
运行时间和输入无关
数据移动是最少的

插入排序
将一个数插入到其他已经有序的数字中的适当位置。为了给要插入的元素腾出空间,需要将其余所有元素在插入之前都向右移动一位。
插入排序所需的时间取决于输入中元素的初始顺序。

希尔排序:--“缩小增量排序”
先将整个待排记录序列分割成为若干子序列分别进行直接插入排 序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。
在希尔排序中,子序列的构成不是简单地“逐段分割”,而是将相隔某个“增量”的记录组成一个子序列。如在第一趟排序时的增量为5,即将相隔为5的元素编成一组进行直接插入排序。第二趟排序时的增量为3,增量进一步缩小。由于在这两趟的插入排序中在子序列中逆序的关键字是跳跃式地移动,从而使得在进行最后一趟增量为1的插入排序时,序列已基本有序,只要作少量比较和移动即可完成排序,因此希尔排序的时间复杂度较直接插入排序低。

起泡排序
起泡排序的过程很简单。首先将第一个记录的关键字和第二个纪录的关键字进行比较,若为逆序(arr[1]>arr[2]),则将两个记录交换之,然后比较第二个纪录和第三个记录的关键字。以此类推,直至第n-1个记录和第n个记录的关键字进行过比较为止。 上述过程成为第一趟起泡排序,其结果使得关键字最大的记录被安置到最后一个记录的位置上。然后进行第二趟起泡排序,对前n-1个记录进行同样的操作,其结果使得关键字次大的记录被安置到第n-1个记录的位置上。
一般地,第i趟排序是从arr[0]到arr[n-i+1]依次比较相邻两个记录的关键字,并在逆序时交换相邻记录,其结果是这n-i+1个记录中关键字最大的记录被交换到第n-i+1的位置上。
整个排序过程需进行k趟起泡排序,显然,判别起泡排序结束的条件应该是“在一趟排序过程中没有进行交换记录的操作”。

快速排序:
1、先从数列中取出一个数作为基准数
2、分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边
3、再对左右区间重复第二步,直到各区间只有一个数。
一趟快速排序的具体做法是:附设两个指针low和high,它们的初值分别为low和high,设枢轴记录的关键字为pivotkey,则首先从high所指位置起向前搜索找到第一个关键字小于pivotkey的记录和枢轴记录互相交换,然后从low所指位置起向后搜索,找到第一个关键字大于pivotkey的记录和枢轴记录互相交换,重复这两步直至low=high为止。
public class Test{ public static void sort(int array[],int low,int high){ int i,j; int index; if(low>high) return; i = low; j = high; index = array[i]; while(i<j){ while(i<j&&array[j]>index) j--; if(i<j) array[i++]=array[j]; while(i<j&&array[i]<index){ i++; } if(i<j) array[j--]==array[i]; } array[i]=index; sort(array,low,i-1); sort(array,i+1,high); } public static void quickSort(int array[]){ sort(array,0,array.length-1); } public static void main(String[] args){ int i=0; int a[]={5,4,9,8,7,6,0,1,3,2}; int len = a.length; quickSort(a); for(int i=0;i<len;i++) System.out.print(a[i]+" "); } }

归并排序:
“归并”的含义是将两个或两个以上的有序表组合成一个新的有序表,也是分治法的典型应用。

堆排序:
堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。
堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了。

线*******************
顺序查找:从表中最后一个记录开始,逐个进行记录的关键字和给定值进行比较,若某个记录的关键字和给定值相等,则查找成功。如果直到第一个记录,其关键字和给定值比较都不等时,则表中没有所差的记录,查找失败。
以有序表表示静态查找表时,可以使用折半查找:先确定待查记录所在的范围(区间),然后逐步缩小范围直到找到或找不到该记录为止。

  • 举例说明:例如:已知的9个数据元素的有序表(1,5,13,19,21,36,37,56,80),现要查找关键字为5的数据元素。 假设指针low和high分别指向待查元素的所在范围的下界和上界,指针mid指示区间的中间位置,即mid=[(low+high)/2]. 在此例中,low=1,high=80,mid=21. 。。。当下届low>high的时候,则表明表中没有关键字等于key的元素,查找不成功。
    若以索引顺序表表示静态查找表,则可以使用分块查找。

动态查找表:
二叉排序树和平衡二叉树

哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
记录的存储位置=f(关键字)
这里的对应关系f称为散列函数,又称为哈希(Hash函数),采用散列技术将记录存储在一块连续的存储空间中,这块连续存储空间称为散列表或哈希表(Hash table)
哈希表有多种不同的实现方法,我接下来解释的是最常用的一种方法——拉链法,我们可以理解为“链表的数组”,如图:

左边很明显是个数组,数组的每个成员包括一个指针,指向一个链表的头,当然这个链表可能为空,也可能元素很多。我们根据元素的一些特征把元素分配到不同的链表中去,也是根据这些特征,找到正确的链表,再从链表中找出这个元素。
两点:
1)、哈希函数是一个映象,因此哈希函数的设定很灵活,只要使得任何关键字由此所得到的的哈希函数值都落在表长允许范围之内即可。
2)、对于不同的关键字可能得到同一哈希地址,这种现象称为冲突。

哈希函数的构造方法:
1)、直接定址法
取关键字或关键字的某个线性函数值为哈希地址。即:
H(key)=key 或H(key)=a*key+b
2)、数字分析法
3)、平方取中法
取关键字平方后的中间几位为哈希地址。这是一种较常用的构造哈希函数的方 法。
4)、折叠法
5)、除留余数法(P的选取很重要)
取关键字被某个不大于哈希表长m的数p除后所得余数为哈希地址。即:
H(key)=key MOD p p<=m
6)、随机数法
选择一个随机函数,取关键字的随机函数值为它的哈希地址,即
H(key)=random(key),其中random为随机函数。通常当关键字长度不等时采用此法构造哈希函数较恰当。
在实际应用中,应根据具体情况,灵活采用不同的方法,并用实际数据测试它的性能,以便做出正确判定。通常应考虑以下五个因素 :
计算哈希函数所需时间 (简单)。
关键字的长度。
哈希表大小。
关键字分布情况。
记录查找频率

处理冲突的方法
1)、开放地址法
Hi=(H(key)+di) MOD m i=1,2,3...k(k<=m-1)
其中H(key)为哈希函数,m 为表长,di称为增量序列。增量序列的取值方式不同,相应的再散列方式也不同。主要有以下三种:
线性探测再散列 di=1,2,3,…,m-1
这种方法的特点是:冲突发生时,顺序查看表中下一单元,直到找出一个空单元或查遍全表。线性探测再散列容易产生“二次聚集”,即在处理同义词的冲突时又导致非同义词的冲突。但可以保证:只要哈希表未填满,总能找到一个不发生冲突的地址。
二次探测再散列 di=12,-12,22,-22,…,k2,-k2 ( k<=m/2 )
这种方法的特点是:冲突发生时,在表的左右进行跳跃式探测,比较灵活。
伪随机探测再散列 di=伪随机数序列。
具体实现时,应建立一个伪随机数发生器,(如i=(i+p) % m),并给定一个随机数做起点。
2)、再哈希法
这种方法是同时构造多个不同的哈希函数:
Hi=RH1(key) i=1,2,…,k
当哈希地址Hi=RH1(key)发生冲突时,再计算Hi=RH2(key)……,直到冲突不再产生。这种方法不易产生聚集,但增加了计算时间。
3)、链地址法
这种方法的基本思想是将所有哈希地址为i的元素构成一个称为同义词链的单链表,并将单链表的头指针存在哈希表的第i个单元中,因而查找、插入和删除主要在同义词链中进行。链地址法适用于经常进行插入和删除的情况。
如,已知一组关键字(32,40,36,53,16,46,71,27,42,24,49,64),哈希表长度为13,哈希函数为:H(key)= key % 13,则用链地址法处理冲突的结果如图8.27所示:

本例的平均查找长度 ASL=(17+24+3*1)=1.5

4)、建立一个公共溢出区
这种方法的基本思想是:将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表

posted @ 2021-12-19 22:32  _无支祁  阅读(56)  评论(0编辑  收藏  举报