算法导论 第八章 线性时间排序

合集下载

Ch6~Ch9 排序、顺序统计

Ch6~Ch9 排序、顺序统计
统计 有序集合 须先排序 O(lg n) 在n个元素的集合中找ith最小元 无序集合 线性 O(n) 2
Chapter 6. 堆排序
3
堆排序(二叉堆) §6 堆排序(二叉堆)
逻辑结构: 逻辑结构:完全二叉树 存贮结构:向量, 存贮结构 : 向量 , 将其看做是完全二叉树的顺序存 储结构 堆性质
15
}
快速排序( §7 快速排序(续)
循环不变量
I. A[p..i] ≤ x II. A[i+1..j-1] > x III. A[j..r-1] 尚未确定 IV. A[r]=x
Note: :
这种划分使得: 这种划分使得:A[p..q-1] ≤ A[q] < A[q+1..r]
16
快速排序( §7 快速排序(续)
21
//在[p..r]中选随机数i
§7 快速排序 (续) 续
3. 随机版本 但随机化算法分析较困难 该算法非常有效, 在排序过程中, 该算法非常有效 , 在排序过程中 , 某次随机选择 最坏不会影响总体效果
Ex 7.2-5 上机作业: 上机作业:写2个快排版本比较之 个快排版本比较之
22
Chapter 8. 线性时间内的排序
k =1 k =1 n n
最好划分: 两子问题大小大致相等) ② 最好划分:(两子问题大小大致相等)
T (n) = 2T (n / 2) + θ (n) = θ (n lg n) //由master定理
18
§7 快速排序 (续) 续
③ 平衡划分
快排平均时间接近于最好情况,设划分总是产生 划分 快排平均时间接近于最好情况,设划分总是产生9:1划分
9
优先队列( §6.5 优先队列(续)

八排序good

八排序good

例 i=1 (49) 38 65 97 76 13 27 i=2 38 (38 49) 65 97 76 13 27 i=3 65 (38 49 65) 97 76 13 27 i=4 97 (38 49 65 97) 76 13 27 i=5 76 (38 49 65 76 97) 13 27 i=6 13 (13 38 49 65 76 97) 27
49
50
65
97 76 38 27
13 输出:13 27 38
76Βιβλιοθήκη 506597 49 38 27
13 输出:13 27 38 49
50
76
65
97 49 38 27
13 输出:13 27 38 49
97
65
97
76
65
76
97
76
65
50 49 38 27
50 49 38 27
50 49 38 27
四趟: 13 27 38 49 [76 97 65 ]
五趟: 13
六趟: 13 排序完毕: 13
27 38 49 65 [97 76 ] 27 38 49 65 76 [97 ] 27 38 49 65 76 97
❖算法描述
❖算法评价 ❖时间简单度 ❖记录移动次数 ❖最好状况:0 ❖❖最比坏较状次况数: :3(n-1 ni)11(ni)12(n2n)
Ch8_2.c
希尔排序(缩小增量法)
排序过程:先取一个正整数d1<n,把全部相隔 d1的记录放一组,组内进展直接插入排序;然后 取d2<d1,重复上述分组和排序操作;直至di=1, 即全部记录放进一个组中排序为止
例 初始: 49 38 65 97 76 13 27 48 55 4 取d1=5 一趟分组:49 38 65 97 76 13 27 48 55 4

算法导论-排序(四)计数排序(线性时间排序)

算法导论-排序(四)计数排序(线性时间排序)

算法导论-排序(四)计数排序(线性时间排序)⽬录1、计数排序介绍2、流程图3、代码实现4、性能分析5、参考资料内容1、计数排序介绍什么是计数排序?计数排序是⼀种特殊的排序算法,之前介绍的排序算法需要对数进⾏两两⽐较,效率下界为θ(nlgn); ⽽计数排序不需要对数进⾏⽐较就可以进⾏排序;很神奇吧,只需要对待排序数组进⾏遍历就可以排序,效率为Θ(n)。

哈哈,那么神奇,下⾯开讲限制:计数排序只能对⾮负整数(0,1,2,3...N)进⾏排序排序思想:计数排序的基本思想就是对每⼀个输⼊元素 x,确定出⼩于 x 的元素个数。

有了这⼀信息,就可以把 x 直接放到它在最终输出数组中的位置上。

例如:有 10 个年龄不同的⼈,统计出有 8 个⼈的年龄⽐ A ⼩,那 A 的年龄就排在第 9 位,⽤这个⽅法可以得到其他每个⼈的位置,也就排好了序。

2、流程图排序算法步骤:1)统计数组中每个值为 X 的元素出现的次数,存⼊数组 C 的第X 项2)累加元素出现次数(计算不超过 X包括X 的元素的个数)3) 将元素X依次放⼊到适当的位置排序伪码:CountSort(A,n,k) //A-待排序数组;n-排序数组元素个数;k-⼤于等于待排序数组元素最⼤值的某个整数步骤⼀流程图 1)统计数组中每个值为 X 的元素出现的次数,存⼊数组 C 的第X 项步骤⼆流程图 2)累加元素出现次数(计算不超过 X包括X 的元素的个数)步骤三流程图 3)将元素X依次放⼊到适当的位置3、代码实现(c++)1 #include <iostream>2 #include <vector>3 #include <time.h>4using namespace std;56#define N 10 //排序数组⼤⼩7#define K 100 //排序数组范围0~K89void CountSort(vector<int> &A)10 {11//找出待排序数组最⼤、最⼩值12int min,max;13 min=max=A[0];14for (int i=1;i<A.size();i++)15 {16if (A[i]<min) min=A[i];17else if (A[i]>max) max=A[i];18 }19//定义数组B存放排好的数20 vector<int> B(A.size());21//定义数组C,⼤⼩为(max-min+1),C[i]为A中值为i的个数22 vector<int> C(max-min+1);23for (int i=0;i<max-min+1;i++) C[i]=0;//初始为024for(int i=0;i<A.size();i++) C[A[i]-min]++;//计数25for (int i=1;i<max-min+1;i++) C[i]+=C[i-1];//累加26for (int i=A.size()-1;i>=0;i--)27 {28 B[C[A[i]-min]-1]=A[i];//A中值倒序取出放到B中合适位置,并在C计数中减129//因数组下标从0开始,所以减130 C[A[i]-min]--;31 }32 A.assign(B.begin(),B.end());//B赋给A33 }34////打印数组35void print_element(vector<int> A)36 {37int len=A.size();38for (int i=0;i<len;i++)39 {40 std::cout<<A[i]<<"";41 }42 std::cout<<std::endl;43 }44// 随机参数排序数组,产⽣数组范围0~k的整数45void Random(vector<int> &a,int n,int k)46 {47int i=0;48 srand( (unsigned)time( NULL ) );49while(i<n)50 {51 a[i++]=rand()%k;52 }53 }5455int main()56 {57 vector<int > vec_int(N);58 Random(vec_int,N,K);59 cout<<"源数组: ";60 print_element(vec_int);61 CountSort(vec_int);62 cout<<"以排序数组: ";63 print_element(vec_int);6465 system("PAUSE");66return0;67 }4、性能分析分析性能好的快速排序和本节介绍的计数排序的效率【排序数组取值为0~100的整数,数组⼤⼩分别取100,1000,10000,100000测试】数组⼤⼩N快速排序(ms)计数排序(ms)1000.1530120.2369821000 6.00759 4.612281000058.442216.01871000004176.58169.768分析:当数组元素个数较⼤时,计数排序效率相当⾼!注意:当排序数组元素个数较少时效率会降低,并且数组范围较⼤时内存消耗会相对增多。

Python线性时间排序——桶排序、基数排序与计数排序

Python线性时间排序——桶排序、基数排序与计数排序

Python线性时间排序——桶排序、基数排序与计数排序1. 桶排序1.1 范围为1-M的桶排序如果有⼀个数组A,包含N个整数,值从1到M,我们可以得到⼀种⾮常快速的排序,桶排序(bucket sort)。

留置⼀个数组S,⾥⾯含有M个桶,初始化为0。

然后遍历数组A,读⼊A i时,S[A i]增⼀。

所有输⼊被读进后,扫描数组S得出排好序的表。

该算法时间花费O(M+N),空间上不能原地排序。

初始化序列S遍历A修改序列S的项举个例⼦,排序⼀个数组[5,3,6,1,2,7,5,10]值都在1-10之间,建⽴10个桶:[0 0 0 0 0 0 0 0 0 0] 桶[1 2 3 4 5 6 7 8 9 10] 桶代表的值遍历数组,第⼀个数字5,第五个桶加1[0 0 0 0 1 0 0 0 0 0]第⼆个数字3,第三个桶加1[0 0 1 0 1 0 0 0 0 0]遍历后[1 1 1 0 2 1 1 0 0 1]输出[1 2 3 5 5 6 7 10]代码import randomclass bucketSort(object):def _max(self,oldlist):_max=oldlist[0]for i in oldlist:if i>_max:_max=ireturn _maxdef _min(self,oldlist):_min=oldlist[0]for i in oldlist:if i<_min:_min=ireturn _mindef sort(self,oldlist):_max=self._max(oldlist)_min=self._min(oldlist)s=[0 for i in xrange(_min,_max+1)]for i in oldlist:s[i-_min]+=1current=_minn=0for i in s:while i>0:oldlist[n]=currenti-=1n+=1current+=1def __call__(self,oldlist):self.sort(oldlist)return oldlistif __name__=='__main__':a=[random.randint(0,100) for i in xrange(10)]bucketSort()(a)print a1.2 区间[0,1)均匀分布的桶排序当输⼊符合均匀分布时,例如,元素均匀的分布在区间[0,1)上,可以将桶排序与其它排序⽅法结合使⽤。

(完整版)数据结构与算法第8章答案

(完整版)数据结构与算法第8章答案

第8 章排序技术课后习题讲解1. 填空题⑴排序的主要目的是为了以后对已排序的数据元素进行()。

【解答】查找【分析】对已排序的记录序列进行查找通常能提高查找效率。

⑵对n个元素进行起泡排序,在()情况下比较的次数最少,其比较次数为()。

在()情况下比较次数最多,其比较次数为()。

【解答】正序,n-1,反序,n(n-1)/2⑶对一组记录(54, 38, 96, 23, 15, 72, 60, 45, 83)进行直接插入排序,当把第7个记录60插入到有序表时,为寻找插入位置需比较()次。

【解答】3【分析】当把第7个记录60插入到有序表时,该有序表中有2个记录大于60。

⑷对一组记录(54, 38, 96, 23, 15, 72, 60, 45, 83)进行快速排序,在递归调用中使用的栈所能达到的最大深度为()。

【解答】3⑸对n个待排序记录序列进行快速排序,所需要的最好时间是(),最坏时间是()。

【解答】O(nlog2n),O(n2)⑹利用简单选择排序对n个记录进行排序,最坏情况下,记录交换的次数为()。

【解答】n-1⑺如果要将序列(50,16,23,68,94,70,73)建成堆,只需把16与()交换。

【解答】50⑻对于键值序列(12,13,11,18,60,15,7,18,25,100),用筛选法建堆,必须从键值为()的结点开始。

【解答】60【分析】60是该键值序列对应的完全二叉树中最后一个分支结点。

2. 选择题⑴下述排序方法中,比较次数与待排序记录的初始状态无关的是()。

A插入排序和快速排序B归并排序和快速排序C选择排序和归并排序D插入排序和归并排序【解答】C【分析】选择排序在最好、最坏、平均情况下的时间性能均为O(n2),归并排序在最好、最坏、平均情况下的时间性能均为O(nlog2n)。

⑵下列序列中,()是执行第一趟快速排序的结果。

A [da,ax,eb,de,bb] ff [ha,gc]B [cd,eb,ax,da] ff [ha,gc,bb]C [gc,ax,eb,cd,bb] ff [da,ha]D [ax,bb,cd,da] ff [eb,gc,ha]【解答】A【分析】此题需要按字典序比较,前半区间中的所有元素都应小于ff,后半区间中的所有元素都应大于ff。

【算法导论】排序(四):决策树、线性时间排序(计数、基数、桶排序)

【算法导论】排序(四):决策树、线性时间排序(计数、基数、桶排序)

【算法导论】排序(四):决策树、线性时间排序(计数、基数、桶排序)到⽬前为⽌,⼀共整理总结了五⼤排序算法:1、插⼊排序2、冒泡排序、选择排序、交换排序(把这三种⽅法归为⼀种,因为他们的思想本质上都是⼀样的)3、归并排序4、堆排序5、快速排序以上五种排序都可以称为“⽐较排序”,顾名思义,因为他们都是基于⽐较元素来决定其相对位置的。

其中前两种的时间为O(n^2),归并排序和堆排序最坏O( n lg n ),快排平均O( n lg n )定理:任意⼀种⽐较排序算法最坏情况下,都需要做Ω( n lg n )次的⽐较。

我们通过决策树来证明:●决策树(decision tree)⽐较排序可以被抽象的视为决策树。

撒⼀颗决策树是⼀颗满⼆叉树,表⽰某排序算法作⽤于给定输⼊元素所作的所有⽐较,⽽其它因素忽略。

假设有⼀组三个元素的序列,我们⽤1,2,3来分别表⽰这三个元素,我们基于⽐较来对它排序,可以有下列决策树:不难发现,判定树的叶⼦表⽰了三个元素的所有可能排列。

另外,⽤⽐较排序对这三个元素进⾏排序的话,你总可以找到⼀条路径来表⽰它的整个⽐较过程。

(需要注意的是,1并不表⽰它代表第⼀个元素,它可以代表三个元素中任意⼀个。

2,3也相同。

但是1,2,3不指向相同元素)。

显然最坏情况下的复杂度即是判定树的⾼。

对于⼀颗⾼度为H的、具有L个可达叶节点的决策树,它对应于对N个元素所作的⽐较排序。

因为N个元素有N!种排列(排列组合知识),每⼀种都作为⼀个叶⼦出现在书中,故有N!<=L(重要,注:)有⼜由于在⼀颗⾼为H的⼆叉树中,叶⼦的数⽬不多于2^H,则有N! <= L <= 2^H对该式⼦取对数,得到:H>=lg(N!) (因为lg函数时单调递增的)=Ω(N lg N)注:⼀开始我以为应该是等于的关系,后来百度了⼀下,原⽂有这⼀句:Because each of the N! permutation appears as areachable leaf. 作者的意思着重于⽤N!来表⽰N个元素的所有可能排列,但是N个元素的所有可能排列实际上是⼩于等于N!的,因为在N个元素中有可能有相等的元素。

算法导论 第八章答案

算法导论 第八章答案

{ if(m >n)
cout<<"区间输入不对"<<endl; else { if(n <0) else if(m <=0&& n <= k) else if(n > k && m >0) else if(n > k && m <=0) else
cout<<"个数为"<<0<<endl; cout<<"个数为"<<c[n]<<endl; cout<<"个数为"<<c[k] - c[m -1]<<endl;
cout<<"个数为"<<c[k]<<endl; cout<<"个数为"<<c[n] - c[m -1]<<endl;
}}
return 0;
}
void counting_sort(int*&a, int length, int k, int*&b, int*&c)
{ for(int i =0; i < k +1; i++)
const int k =2504; int* c =new int[k +1];
counting_sort(a, LEN, k, b, c); //这里需要注释掉
//for(int i = 0; i < LEN; i++)
// cout<<b[i]<<endl;

麻省理工学院-算法导论

麻省理工学院-算法导论

麻省理工学院-算法导论关于课本的介绍如下:本书自第一版出版以来,已经成为世界范围内广泛使用的大学教材和专业人员的标准参考手册。

本书全面论述了算法的内容,从一定深度上涵盖了算法的诸多方面,同时其讲授和分析方法又兼顾了各个层次读者的接受能力。

各章内容自成体系,可作为独立单元学习。

所有算法都用英文和伪码描述,使具备初步编程经验的人也可读懂。

全书讲解通俗易懂,且不失深度和数学上的严谨性。

第二版增加了新的章节,如算法作用、概率分析与随机算法、线性编程等,几乎对第一版的各个部分都作了大量修订。

学过计算机的都知道,这本书是全世界最权威的算法课程的大学课本了,基本上全世界的名牌大学用的教材都是它。

这本书一共四位作者,Thomas H. Cormen,Charles E. Leiserson和Ronald L. Rivest是来自MIT的教授,Clifford Stein是MIT出来的博士,现在哥伦比亚大学做教授,四人姓氏的首字母联在一起即是此书的英文简称(CLRS 2e),其中的第三作者Ronald L. Rivest是RSA算法的老大(算法名字里面的R即是指他),四个超级大牛出的一本书,此书不看人生不能算完整。

再介绍一下课堂录像里面授课的两位MIT的老师,第一位,外表“绝顶聪明”的,是本书的第二作者Charles E. Leiserson,以逻辑严密,风趣幽默享誉MIT。

第二位,留着金黄色的络腮胡子和马尾发的酷哥是Erik Demaine,21岁即取得MIT教授资格的天才,1981出生,今年才25岁,业余爱好是俄罗斯方块、演戏、琉璃、折纸、杂耍、魔术和结绳游戏。

另外,附上该书的中文电子版,pdg转pdf格式,中文版翻译自该书的第一版,中文书名没有使用《算法导论》,而使用的是《现代计算机常用数据结构和算法》,1994年出版时没有得到国外的授权,属于“私自翻译出版”,译者是南京大学计算机系的潘金贵。

课程重点算法导论是麻省理工学院电机工程与计算机科学系“理论计算机科学”集中选修课程的先导科目。

算法导论6.5-8堆排序

算法导论6.5-8堆排序
1
//否则
if(largest != i) { //根与值最大的结点交互 swap(A[i], A[largest]); //交换可能破坏子树的堆,重新调整子树 Max_Heapify(A, largest); } }
//建堆,时间是O(nlgn) void Build_Max_Heap(node *A) { heap_size = length; //从堆中最后一个元素开始,依次调整每个结点,使符合堆的性质 for(int i = length / 2; i >= 1; i--) Max_Heapify(A, i); }
2
//main.cpp #include <iostream> #include "Heap.h" using namespace std;
int main() { //5个链表,每个链表的头结点放入Head中 node *Head[5] = {0},*tail[5] = {0}; int i, j, list, value; int temp; //构造需要合并的数据 for(value = 50; value >0; value--) { list = rand() % 5; node *a = new node; a->list = list; a->value = value; if(Head[list] == NULL) Head[list] = a; else tail[list]->next = a; tail[list] = a; } //显示待排序数据 cout<<"显示待排序数据"<<endl; for(i = 0; i < 5; i++) { cout<<i<<':'<<endl; node *p = Head[i]; while(p) { cout<<p->value<<' '; p = p->next; } cout<<endl; } length = 0;heap_size = 0; int ans[55] = {0};//合并结果存放在这里 node A[6];//堆的大小是k //step1:取每个链表的第一个元素,构造成一个含有k个元素的堆 for(i = 0; i < 5; i++) { if(Head[i]) { Max_Heap_Insert(A, *Head[i]); Head[i] = Head[i]->next; } } while(1) { list = A[1].list; //step2:把根结点的值记入排序结果中 ans[++ans[0]] = A[1].value;

算法导论part_II---排序和顺序统计

算法导论part_II---排序和顺序统计

19
决策树举例
排序〈a1, a2, …, an〉
每个内部节点标识为 i:j i, j ∈{1, 2,…, n}. •左子树表示当ai ≤ aj时的比较序列 . •右子树表示当ai ≥ aj时的比较序列 .
20
决策树举例
排序 〈a1, a2, a3〉 = 〈9 , 4 , 6 〉:
每个内部节点标识为i:j,i,j∈{1, 2,…, n}. •左子树表示当ai≤aj时的比较序列 . •右子树表示当ai≥aj时的比较序列 .
《Introduction To Algorithms》
算法导论 Part II:排序和顺序统计
报告人:熊正强
1
主要内容
6.堆排序 7.快速排序 8.线性时间排序 9.中位数和顺序统计
Chapter 6. 堆排序
3
堆排序(Heap Sort)
堆排序(Heap Sort) 1.堆的定义
K[high..n]>x high 还未处理元素
X
Low K[1..low]<=X
pivot
Step2: 求解
递归调用快速排序, 对左、右子区间K[low..pivotpos1]和K[pivotpos+1..high]快速排序.
QuickSort(Elem K[ ], int low, int high){ if (low < high) { //长度大于1
31
循环2
for j←1 to n do C[A[j]] ←C[A[j]] + 1 ⊳ C[i] = |{key = i}|
32
循环2
for j←1 to n do C[A[j]] ←C[A[j]] + 1 ⊳ C[i] = |{key = i}|

经典算法总结之线性时间做选择

经典算法总结之线性时间做选择

经典算法总结之线性时间做选择问题:输⼊:⼀个包含n个(不同的)数的集合A和⼀个数i, 1 <= I <= n。

输出:元素x∈A,它恰⼤于A中其他的I – 1个元素(即求第k⼩数)。

本博⽂中这篇⽂章也⽤了本⽂中的算法,⼤家可以参考。

三种算法:1、直接排序,输出数组第i个元素即可, 时间复杂度为O(nlgn)2、这种算法,利⽤“快排的或者类似⼆分”的思想,每次以枢纽为界,分两边,每次只需处理⼀边即可(抛弃另⼀边),平均情况下的运⾏时间界为O(n),这种算法以期望时间做选择。

《算法都论》⾥是,在分治时⽤随机数来选取枢纽(算法导论中伪代码见图),好吧,这是理论上的算法,它没有考虑实际产⽣随机数的开销,事实上,效率⼀点也不⾼,已经测试过,产⽣随机数花费的开销真的很⼤,后边我⽤更快的三数中值⼜实现了⼀遍,思想是⼀样的,只是效率提⾼了。

C++完整代码:#include <iostream>#include <vector>#include <algorithm>using namespace std;int partition(vector<int> &A,int p,int r){int x = A[r];int i=p-1;int temp;for(int j = p;j<r;++j){if(A[j]<=x){++i;swap(A[i],A[j]);}}swap(A[i+1],A[r]);return i+1;}inline int Random(int low, int high) {return (rand() % (high - low + 1)) + low;}int Randomized_Partition(vector<int> &kp, int low, int high) {int i = Random(low, high);swap(kp[high], kp[i]);return partition(kp, low, high);}void randomized_quickSort(vector<int> &A,int p,int r){if(p<r){int q = Randomized_Partition(A,p,r);randomized_quickSort(A,p,q-1);randomized_quickSort(A,q+1,r);}}int randomized_select(vector<int> A,int p,int r,int i){if(p==r)return A[p];if(p>r) return -1;int q = Randomized_Partition(A,p,r);int k = q-p+1;if(i==k)return A[q];else if(i<k)return randomized_select(A,p,q-1,i);else return randomized_select(A,q+1,r,i-k);}void main(){int a[10] = {9,10,8,7,6,5,4,3,2,1};vector<int> A(a,a+10);cout<<randomized_select(A,0,9,5)<<endl;}3、第三种算法以最坏情况线性时间做选择,最坏运⾏时间为O(n),这种算法基本思想是保证每个数组的划分都是⼀个好的划分,以5为基,五数取分,这个算法,算法导论没有提供伪代码,额,利⽤它的思想,可以快速返回和最终中位数相差不超过2的数,这样的划分接近最优,基本每次都⼆分了(算法导论中步骤见图)/*利⽤中位数来选取枢纽元,这种⽅法最坏情况下运⾏时间是O(n)这⾥求的中位数是下中位数算法导论⾥没有伪代码,写起来很⿇烦注意这⾥的查找到的中位数,并不是真正意义上的中位数⽽是和真正中位数相差不超过2的⼀个数开始以为我写错了,⼜看了算法导论,应该就是这个意思返回的是[x - 1, x + 2]的⼀个数,中位数是x从下边的输出中也可以看出:*/ #include<iostream>#include<cstdio>using namespace std;const int maxn = 14;//kp -> sizeconst int maxm = maxn / 5 + 1;//mid -> sizeint kp[maxn];int mid[maxm]; //插⼊排序void InsertionSort(int kp[], int n) {for (int j, i = 1; i < n; i++) {int tmp = kp[i];for (j = i; j > 0 && kp[j - 1] > tmp; j--) {kp[j] = kp[j - 1];}kp[j] = tmp;}} //查找中位数, 保证每⼀个划分都是好的划分int FindMedian(int kp[], int low, int high) {if (low == high) {return kp[low];}int index = low;//index初始化为low//如果本⾝⼩于5个元素,这⼀步就跳过if (high - low + 1 >= 5) { //储存中位数到mid[]for (index = low; index <= high - 4; index += 5) {InsertionSort(kp + index, 5);int num = index - low;mid[num / 5] = kp[index + 2];}} //处理剩下不⾜5个的元素int remain = high - index + 1;if (remain > 0) {InsertionSort(kp + index, remain);int num = index - low;mid[num / 5] = kp[index + (remain >> 1)];//下中位数}int cnt = (high - low + 1) / 5;if ((high - low + 1) % 5 == 0) {cnt--;//下标是从0开始,所以需要-1}//存放在[0…tmp]if (cnt == 0) {return mid[0];} else {return FindMedian(mid, 0, cnt);}} int Qselect(int kp[], int low, int high, int k) {int pivotloc = FindMedian(kp, low, high); //这⾥有点不⼀样,因为不知道pivotloc下标,所以全部都要⽐较int i = low - 1, j = high + 1;for (; ;) {while (kp[++i] < pivotloc) {}while (kp[--j] > pivotloc) {}if (i < j) swap(kp[i], kp[j]);else break;} int num = i - low + 1;if (k == num) return kp[i];if (k < num) {return Qselect(kp, low, i - 1, k);} else {return Qselect(kp, i + 1, high, k - num);}}int main() {int kp[maxn] = {10, 14, 8, 11, 7, 1, 2, 13, 3, 12, 4, 9, 6, 5};for (int i = 0; i < maxn; i++) {printf("中位数是: %d\n", FindMedian(kp, 0, maxn - 1));printf("第%d⼩的数是: ", i + 1);cout << Qselect(kp, 0, maxn - 1, i + 1) << endl << endl;}return 0;}。

算法导论中文版答案

算法导论中文版答案

24.2-3
24.2-4
24.3-1 见图 24-6 24.3-2
24.3-3
24.3-4 24.3-5 24.3-6
24.3-7
24.3-8 这种情况下不会破坏已经更新的点的距离。 24.4**** 24.5****
25.1-1 见图 25-1 25.1-2 为了保证递归定义式 25.2 的正确性 25.1-3
8.3-3 8.3-4
8.3-5(*) 8.4-1 见图 8-4 8.4-2
8.4-3 3/2,1/2 8.4-4(*) 8.4-5(*)
9.1-1
9.1-2 9.2-1 9.3-1
第九章
9.3-2 9.3-3
9.3-4 9.3-5
9.3-6 9.3-7
9.3-8
9.3-9
15.1-1
6.4-4
6.4-5
6.5-1 据图 6-5 6.5-2
6.5-3 6.5-4 6.5-5
6.5-6 6.5-7
6.5-8
7.1-1 见图 7-1 7.1-2
7.1-3 7.1-4 7.2-1 7.2-2
7.2-3 7.2-4 7.2-5
第七章
7.2-6 7.3-1
7.3-2
7.4-1 7.4-2
5.3-6
6.1-1 6.1-2 6.1-3 6.1-4 6.1-5 6.1-6
第6章
6.1-7
6.2-1 见图 6-2 6.2-2
6.2-3
6.2-4
6.2-5 对以 i 为根结点的子树上每个点用循环语句实现 6.2-6
6.3-1
见图 6-3 6.3-2
6.3-3
6.4-1 见图 6-4 6.4-2 HEAPSORT 仍然正确,因为每次循环的过程中还是会运行 MAX-HEAP 的过程。 6.4-3
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Decision-tree example
• Sort <a1,a2, a3>=<9,4,6>
1:2
• A decision tree can model the execution of any comparison sort: --One tree for each input size n. --View the algorithm as splitting whenever it compares two elements. -- The tree contains the comparisons along all possible instruction traces. --The running time of the algorithm = the length of the path taken. -- Worst-case running time = height of tree.
Decision-tree example
• Sort <a1,a2, a3>=<9,4,6>
1:2
2:3
1:3
123
1:3
213
2:3 4≤6
132
312
231
321
• Each internal node is labelled i:j for i,j∈{1,2,…,n} --The left subtree shows subsequent comparisons if ai≤aj --The right subtree show subsequent comparisons if ai>aj
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 2 1
5
3
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 2
5
3
4
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 2
4 5
3
4
Counting-sort example
Sorting Lower bound
• Is there a faster algorithm? • How if using a different model of computation, …

Counting Sort计数排序 Counting sort: No comparisons between elements
Decision-tree example
• Sort <a1,a2, a3>=<9,4,6>
1:2
2:3
1:3
123
1:3
213
2:3
132
312
231
321
• Each internal node is labelled i:j for i,j∈{1,2,…,n} --The left subtree shows subsequent comparisons if ai≤aj --The right subtree show subsequent comparisons if ai>aj
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 3
5 2
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 3 1
5
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 3 1
• A: Yes, as long as we use comparison sorts
• TODAY: Prove any comparison sort has Ω(n lgn) worst case running time.
Decision-tree example决策树/判定树
• Sort <a1,a2,…,an>
Decision-tree example
• Sort <a1,a2, a3>=<9,4,6>
1:2 9>4
2:3
1:3
123
1:3
213
2:3
132
312
231
321
• Each internal node is labelled i:j for i,j∈{1,2,…,n} --The left subtree shows subsequent comparisons if ai≤aj --The right subtree show subsequent comparisons if ai > aj
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
0
0 0
0
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4Байду номын сангаас5
C:
0
0 0
0
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
0
0 0
1 0
Counting-sort example
Decision-tree example
• Sort <a1,a2, a3>=<9,4,6>
1:2
2:3
1:3 9>6
123
1:3
213
2:3
132
312
231
321
• Each internal node is labelled i:j for i,j∈{1,2,…,n} --The left subtree shows subsequent comparisons if ai≤aj --The right subtree show subsequent comparisons if ai>aj

Input: A[1..n], where A[j] ∈{1,2,…,k} Output: B[1..n], sorted Auxiliary storage: C[1..k]

For x in A, if there are 17 elements less than x in A, then x belongs in output position 18(值为x的元素唯一) How if several elements in A have the same value? (值为 x的元素不唯一)


Put the 1st in position 18, 2nd in position 19,3rd in position 20,…

How if there are 17 elements not greater than x in A? (值为x的元素可能不唯一)

Put the last one in position 17, the penultimate one in position 16,…
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
4 3
4 5
C:
1
1 2 1
4
3
4
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
lg is mono. increasing ∴ h ≥ lg (n!) Stirling’s formula ≥ lg (n/e)n = n lg n - n lg e =Ω(n lg n)
Lower Bound for Comparison Sorting
• Corollary. Heapsort and merge sort are asymptotically optimal comparison sorting algorithms.
5
Counting-sort example
1
2
3
4
5
1
2
3
4
A: B:
4 1
1 2
3
3
相关文档
最新文档