1、2022-4-191contents 9.1 概述概述 9.2 插入排序插入排序1.1.直插排序直插排序2.2.二分插入排序二分插入排序 3.3.希尔排序希尔排序 9.3 交换排序交换排序1.1.冒泡排序冒泡排序2.2.快速排序快速排序 9.4 选择排序选择排序1.1.直选排序直选排序2.2.堆排序堆排序 9.5 归并排序归并排序1.1.二路归并排序二路归并排序2022-4-1929.1 概述概述 排序定义排序定义将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列叫 排序分类排序分类按待排序记录所在位置 内部排序:待排序记录存放在内存 外部排序:排序过程中需对外存进行访问的排
2、序按排序依据原则 插入排序:直接插入排序、折半插入排序、希尔排序 交换排序:冒泡排序、快速排序 选择排序:简单选择排序、堆排序 归并排序:2-路归并排序 基数排序2022-4-193 按排序所需工作量 简单的排序方法:T(n)=O(n) 先进的排序方法:T(n)=O(logn) 基数排序:T(n)=O(d.n) 排序基本操作排序基本操作 比较两个关键字大小 将记录从一个位置移动到另一个位置2022-4-194 基本思想:基本思想:每次将一个待排序的记录,按其关键字值的大小插入到已经排好序的表中,直至全部插入完成。 根据“寻找寻找”插入位置的方法插入位置的方法不同,插入法可分为:直插排序、二分插
3、入排序、希尔排序。 (1) 直接插入排序直接插入排序 若将一个未排序的元素Li插入到已排序的具有i-1个元素的序列的适当位置,步骤如下: a. 从右向左顺序搜索已排序的序列,若已排序序列中的元素比Li大,则后移一个位置,直至找到一个元素Lj-1(0j-1i-1)的关键字值比Li的关键字值小; b. 将Li插入表中第j个位置上,成为Lj。9.2 插入排序插入排序2022-4-195例49 38 65 97 76 13 27i=2 38 (38 49) 65 97 76 13 27i=3 65 (38 49 65) 97 76 13 27i=4 97 (38 49 65 97) 76 13 27i
4、=5 76 (38 49 65 76 97) 13 27i=6 13 (13 38 49 65 76 97) 27i=1 ( )i=7 (13 38 49 65 76 97 ) 2727jjjjjj977665493827 (13 27 38 49 65 76 97)排序结果:2022-4-196void InsertSort(int a,const int n) for(int i=1;in;i+) /i表示插入次数,共进行表示插入次数,共进行n-1次插入次插入if(aiai-1) /将将ai插入到有序区插入到有序区a0,ai-1中,中,/且且aiai-1int x=ai; /把待排序元素赋
5、给把待排序元素赋给 x/从从ai-2开始比较开始比较for(int j=i-1; (x=0); j-)aj+1=aj; /从从ai-1开始后移一位开始后移一位/直到找到一个元素,插入到正确位置直到找到一个元素,插入到正确位置aj+1=x; 2022-4-197 算法评价 时间复杂度 若待排序记录按关键字从小到大排列(正序)Y关键字比较次数:112nniY记录移动次数:)1(222nni 若待排序记录按关键字从大到小排列(逆序)Y关键字比较次数:2)1)(2(2nniniY记录移动次数:2)1)(4()1(2nnini 若待排序记录是随机的,取平均值Y关键字比较次数:42nY记录移动次数:42n
6、T(n)=O(n)2022-4-198 (2) 折半插入排序折半插入排序 排序过程:用折半查找方法确定插入位置的排序叫例i=1 (30) 13 70 85 39 42 6 20i=2 13 (13 30) 70 85 39 42 6 20i=7 6 (6 13 30 39 42 70 85 ) 20.i=8 20 (6 13 30 39 42 70 85 ) 20sjmi=8 20 (6 13 30 39 42 70 85 ) 20sjmi=8 20 (6 13 30 39 42 70 85 ) 20sjmi=8 20 (6 13 30 39 42 70 85 ) 20sji=8 20 (6
7、13 20 30 39 42 70 85 )2022-4-199 算法描述时间复杂度:T(n)=O(n)void BinsertSort(int a,const int n)for(int i=1;in;i+) int b=ai;int low=0;int high=i-1;while(low=high) int m=(low+high)/2;if(b=high+1;j-)aj+1=aj;ahigh+1=b;2022-4-1910 (3) 希尔排序希尔排序(缩小增量法缩小增量法) 排序过程:先取一个正整数d1n,把所有相隔d1的记录放一组,组内进行直接插入排序直接插入排序;然后取d2d1,重复
8、上述分组和排序操作;直至di=1,即所有记录放进一个组中排序为止。2022-4-1911取d3=1三趟分组:13 27 48 55 4 49 38 65 97 76三趟排序:4 13 27 38 48 49 55 65 76 97例 初始: 49 38 65 97 76 13 27 48 55 4一趟排序:13 27 48 55 4 49 38 65 97 76二趟排序:13 4 48 38 27 49 55 65 97 76取d1=5一趟分组:49 38 65 97 76 13 27 48 55 4取d2=3二趟分组:13 27 48 55 4 49 38 65 97 762022-4-19
9、12 算法描述算法描述例49 38 65 97 76 13 27 48 55 4#define T 3int d=5,3,1;ji49133827一趟排序:13 27 48 55 4 49 38 65 97 76jiji274jiji55ji38jijiji二趟排序: 13 4 48 38 27 49 55 65 97 76jiji6548ji9755ji7642022-4-1913void ShellInsert(int a, int n, int dk)for(int i=dk;in;i+)if(ai=0)&(baj);j-=dk)aj+dk=aj;aj+dk=b;void ShellSo
10、rt(int a,int n,int dlta,int t)for(int k=0;kr2.key,则交换;然后比较第二个记录与第三个记录;依次类推,直至第n-1个记录和第n个记录比较为止第一趟冒泡排序,结果关键字最大的记录被安置在最后一个记录上。 对前n-1个记录进行第二趟冒泡排序,结果使关键字次大的记录被安置在第n-1个记录位置。 重复上述过程,直到“在一趟排序过程中没有进行过交换记录的操作”为止。9.3 交换排序交换排序2022-4-1916例49 38 65 97 76 13 27 30初始关键字38 49 65 76 13 27 30 97第一趟38 49 65 13 27 30 7
11、6第二趟38 49 13 27 30 65第三趟38 13 27 30 49第四趟13 27 30 38第五趟13 27 30第六趟384976971397279730971376767627301365276530651313494930492738273830382022-4-1917void bubble_sort(JD r, int n) int m,i,j,flag=1; /当当flag为为0则停止排序则停止排序JD x;m=n-1;while(m0)&(flag=1) /m表示趟数表示趟数flag=0; /开始时元素未交换开始时元素未交换for(j=1; jrj+1.key) /发
12、生逆序发生逆序 flag=1;x=rj;rj=rj+1;rj+1=x; /交换,并标记发生了交换m-;/while 冒泡算法描述2022-4-1918 算法评价 时间复杂度 最好情况(正序)Y比较次数:n-1Y移动次数:0 最坏情况(逆序)Y比较次数:)(21)(211nninniY移动次数:)(23)(321nninniT(n)=O(n)Ch8_4.c2022-4-1919 (2) 快速排序快速排序 基本思想:通过一趟排序,将待排序记录分割成独立的独立的两部分两部分,其中一部分记录的关键字均比另一部分记录的另一部分记录的关键字小关键字小,则可分别对这两部分记录进行排序,以达到整个序列有序。
13、排序过程:对rst中记录进行一趟快速排序,附设两个指针i和j,设基准值基准值记录rp=rs,x=rp.key 初始时令i=s,j=t 首先从j所指位置向前搜索第一个关键字小于x的记录,并和rp交换 再从i所指位置起向后搜索,找到第一个关键字大于x的记录,和rp交换 重复上述两步,直至i=j为止 再分别对两个子序列进行快速排序,直到每个子序列只含有一个记录为止关键字通常取第一个记录的值为基准值。关键字通常取第一个记录的值为基准值。2022-4-1920例初始关键字: 49 38 65 97 76 13 27 50 ijxji 完成一趟排序: ( 27 38 13) 49 (76 97 65 50
14、) 分别进行快速排序: ( 13) 27 (38) 49 (50 65) 76 (97) 快速排序结束: 13 27 38 49 50 65 76 974927ijijij4965ji1349ij4997ij2022-4-1921void qksort(JD r, int t, int w)int i, j, k;JD x;if(t=w) return;i=t; j=w; x=ri;while(ij)while(i=x.key) j-;if(ij) ri=rj; i+; while(ij)&(ri.key=x.key) i+;if(ij) rj=ri; j-; ri=x;qksort(r,t,
15、j-1);qksort(r,j+1,w); 快速算法描述2022-4-1922 算法评价 时间复杂度 最好情况(每次总是选到中间值作枢轴)T(n)=O(nlog2n) 最坏情况(每次总是选到最小或最大元素作枢轴)T(n)=O(n)T(n)=O(n)Ch8_5.c2022-4-1923 (0) 选择排序原理:选择排序原理: 将待排序的结点分为已排序(初始为空)和未排序两组,依次将未排序的结点中值最小的结点未排序的结点中值最小的结点插入已排序的组中。 (1) 直接选择排序过程直接选择排序过程 首先通过n-1次关键字比较,从n个记录中找出关键字最小的记录,将它与第一个记录交换 再通过n-2次比较,从
16、剩余的n-1个记录中找出关键字次小的记录,将它与第二个记录交换 重复上述操作,共进行n-1趟排序后,排序结束9.4 选择排序选择排序2022-4-1924例初始: 49 38 65 97 76 13 27 kjjjjjjkki=11349一趟: 13 38 65 97 76 49 27 i=2kkjjjjj2738二趟: 13 27 65 97 76 49 38 三趟: 13 27 38 97 76 49 65 四趟: 13 27 38 49 76 97 65 五趟: 13 27 38 49 65 97 76 六趟: 13 27 38 49 65 76 97 排序结束: 13 27 38 49
17、 65 76 972022-4-1925void smp_selesort(JD r,int n)int i,j,k;JD x;for(i=1;in;i+)k=i;for(j=i+1;j=n;j+)if(rj.keyrk.key) k=j;if(i!=k)x=ri;ri=rk;rk=x; 选择算法描述2022-4-1926 算法评价 时间复杂度 记录移动次数Y最好情况:0Y最坏情况:3(n-1) 比较次数:)(21)(211nninniT(n)=O(n)Ch8_6.c2022-4-1927 (2) 堆排序堆排序 堆的定义:n个元素的序列(k1, k2, kn),当且仅当满足下列关系时,称之为堆
18、或(i=1,2,.n/2)kik2ikik2i+1kik2ikik2i+1例例 (96,83,27,38,11,9) 例例 (13,38,27,50,76,65,49,97)962791138831327384965765097可将堆序列看成完全二叉树,则堆顶元素(完全二叉树的根)必为序列中n个元素的最小值或最大值2022-4-1928 堆排序:将无序序列建成一个堆,得到关键字最小(或最大)的记录;输出堆顶的最小(大)值后,使剩余的n-1个元素重又建成一个堆,则可得到n个元素的次小值;重复执行,得到一个有序序列,这个过程叫 堆排序需解决的两个问题: 如何由一个无序序列建成一个堆? 如何在输出堆
19、顶元素之后,调整剩余元素,使之成为一个新的堆? 第二个问题解决方法筛选 方法:输出堆顶元素之后,以堆中最后一个元素替代之;然后将根结点值与左、右子树的根结点值进行比较,并与其中小者进行交换;重复上述操作,直至叶子结点,将得到新的堆,称这个从堆顶至叶子的调整过程为“筛选”2022-4-1929例13273849657650979727384965765013输出:132749389765765013输出:139749382765765013输出:13 273849502765769713输出:13 276549502738769713输出:13 27 382022-4-1930496550273
20、8769713输出:13 27 387665502738499713输出:13 27 38 495065762738499713输出:13 27 38 499765762738495013输出:13 27 38 49 506597762738495013输出:13 27 38 49 509765762738495013输出:13 27 38 49 50 652022-4-19317665972738495013输出:13 27 38 49 50 659765762738495013输出:13 27 38 49 50 65 769765762738495013输出:13 27 38 49 50
21、65 76 972022-4-1932int sift(JD r,int k,int m) int i,j;JD x;i=k; x=ri; j=2*i;while(j=m) if(jrj+1.key) j+;if(x.keyrj.key)ri=rj;i=j;j*=2;else j=m+1; ri=x; 筛选算法描述2022-4-1933 第一个问题解决方法 方法:从无序序列的第n/2个元素(即此无序序列对应的完全二叉树的最后一个非终端结点)起,至第一个元素止,进行反复筛选。例 含8个元素的无序序列(49,38,65,97,76,13,27,50)496538271376975049653827
22、137650974913382765765097491338276576509713273849657650972022-4-1934void heapsort(JD r,int n)int i;JD x;for(i=n/2;i=1;i-)sift(r,i,n); /无序序列建堆for(i=n;i=2;i-)x=r1;r1=ri;ri=x; /堆顶元素换到最后sift(r,1,i-1); /调整建堆 堆排序算法描述2022-4-1935 算法评价 时间复杂度:最坏情况下T(n)=O(nlogn) 空间复杂度:S(n)=O(1)Ch8_7.c2022-4-1936 (0) 基本思想: 归并将两个
23、或两个以上的有序表组合成一个新的有序表,叫 (2) 2-路归并排序 排序过程 设初始序列含有n个记录,则可看成n个有序的子序列,每个子序列长度为1 两两合并,得到n/2个长度为2或1的有序子序列 再两两合并,如此重复,直至得到一个长度为n的有序序列为止9.5 归并排序归并排序2022-4-1937例初始关键字: 49 38 65 97 76 13 27一趟归并后: 38 49 65 97 13 76 27二趟归并后: 38 49 65 97 13 27 76三趟归并后: 13 27 38 49 65 76 972022-4-1938void mergesort(JD r,int n)int i
24、,s=1;JD tM;while(sn)tgb(s,n,r,t);s*=2;if(sn) tgb(s,n,t,r); s*=2; else i=1;while(i=n) ri=ti+;2022-4-1939void tgb(int s,int n,JD r,JD t)int i=1;while(i=(n-2*s+1)merge(r,i,i+s-1,i+2*s-1,t);i=i+2*s;if(i(n-s+1) merge(r,i,i+s-1,n,t);else while(i=n) ti=ri+;2022-4-1940void merge(JD r,int h,int m,int w,JD t)
25、int i,j,k;i=h; j=m+1; k=h-1;while(i=m)&(j=w)k+;if(ri.keym)while(j=w) t+k=rj+;elsewhile(i=m) t+k=ri+;2022-4-1941 算法评价 时间复杂度:T(n)=O(nlog2n) 空间复杂度:S(n)=O(n)Ch8_9.c2022-4-1942 基数排序基数排序 多关键字排序 定义:例 对52张扑克牌按以下次序排序:23A23A23A23A两个关键字:花色( ) 面值(23A)并且“花色”地位高于“面值” 多关键字排序方法 最高位优先法(MSD):先对最高位关键字k1(如花色)排序,将序列分成若干
26、子序列,每个子序列有相同的k1值;然后让每个子序列对次关键字k2(如面值)排序,又分成若干更小的子序列;依次重复,直至就每个子序列对最低位关键字kd排序;最后将所有子序列依次连接在一起成为一个有序序列9.6 基数排序基数排序2022-4-1943 最低位优先法(LSD):从最低位关键字kd起进行排序,然后再对高一位的关键字排序,依次重复,直至对最高位关键字k1排序后,便成为一个有序序列 MSD与LSD不同特点 按MSD排序,必须将序列逐层分割成若干子序列,然后对各子序列分别排序 按LSD排序,不必分成子序列,对每个关键字都是整个序列参加排序;并且可不通过关键字比较,而通过若干次分配与收集实现排
27、序 链式基数排序 基数排序:借助“分配”和“收集”对单逻辑关键字进行排序的一种方法 链式基数排序:用链表作存储结构的基数排序2022-4-1944 链式基数排序步骤 设置10个队列,fi和ei分别为第i个队列的头指针和尾指针 第一趟分配对最低位关键字(个位)进行,改变记录的指针值,将链表中记录分配至10个链队列中,每个队列记录的关键字的个位相同 第一趟收集是改变所有非空队列的队尾记录的指针域,令其指向下一个非空队列的队头记录,重新将10个队列链成一个链表 重复上述两步,进行第二趟、第三趟分配和收集,分别对十位、百位进行,最后得到一个有序序列2022-4-1945例初始状态:2781090639
28、30589184505269008083109589269278063930083184505008e0e1e2e3e4e5e6e7e8e9f0f1f2f3f4f5f6f7f8f9一趟分配930063083184505278008109589269一趟收集:2022-4-1946505008109930063269278083184589二趟收集:083184589063505269930e0e1e2e3e4e5e6e7e8e9f0f1f2f3f4f5f6f7f8f9二趟分配008109278930063083184505278008109589269一趟收集:2022-4-194700806
29、3083109184269278505589930三趟收集:109008184930e0e1e2e3e4e5e6e7e8e9f0f1f2f3f4f5f6f7f8f9三趟分配063083269278505589505008109930063269278083184589二趟收集:2022-4-1948 算法描述 算法评价 时间复杂度: 分配:T(n)=O(n) 收集:T(n)=O(rd)T(n)=O(d(n+rd)其中:n记录数 d关键字数 rd关键字取值范围 空间复杂度:S(n)=2rd个队列指针+n个指针域空间Ch8_10.c2022-4-1949初始状态:12781090639305891
30、8450526900808302345678910f0=0 e0=0f1=0 e1=0f2=0 e2=0f3=0 e3=0f4=0 e4=0f5=0 e5=0f6=0 e6=0f7=0 e7=0f8=0 e8=0f9=0 e9=0112233445667789104930063083184505278008109589269031067192582022-4-1950f0=0 e0=0f1=0 e1=0f2=0 e2=0f3=0 e3=0f4=0 e4=0f5=0 e5=0f6=0 e6=0f7=0 e7=0f8=0 e8=0f9=0 e9=0134477 910493006308318450
31、527800810958926903106719258一趟收集:31016258750500810993006326927808318458909243811065二趟收集:2022-4-1951750500810993006326927808318458909243811065二趟收集:f0=0 e0=0f1=0 e1=0f2=0 e2=0f3=0 e3=0f4=0 e4=0f5=0 e5=0f6=0 e6=0f7=0 e7=0f8=0 e8=0f9=0 e9=04479287928900806308310918426927850558993003102681754三趟收集:311065p
32、经常不断地学习,你就什么都知道。你知道得越多,你就越有力量p Study Constantly, And You Will Know Everything. The More You Know, The More Powerful You Will Be学习总结结结束束语语当当你尽你尽了自己的最大努力了自己的最大努力时时,失失败败也是也是伟伟大大的的,所以不要放弃,所以不要放弃,坚坚持就是正确的。持就是正确的。When You Do Your Best, Failure Is Great, So DonT Give Up, Stick To The End演演讲讲人:人:XXXXXX 时时 间间:XX年年XX月月XX日日
侵权处理QQ:3464097650--上传资料QQ:3464097650
【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。