程序设计培训讲义5:排序与查找ppt课件_第1页
程序设计培训讲义5:排序与查找ppt课件_第2页
程序设计培训讲义5:排序与查找ppt课件_第3页
程序设计培训讲义5:排序与查找ppt课件_第4页
程序设计培训讲义5:排序与查找ppt课件_第5页
已阅读5页,还剩38页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、程序设计培训五排序与查找.一、顺序查找基本思想: 从第一个元素或最后一个元素开始,逐个把数据元素的关键字值和给定值比较,若某个元素的关键字值和给定值相等,则查找成功。否则,若直至第n个数据元素都不相等,说明不存在满足条件的数据元素,查找失败。 算法特点:算法简单,既适用于以顺序存储结构组织的查找表的查找,也适用于以链式存储结构组织的查找表的查找;但执行效率低。.#includeint search (int a, int n, int k) /*a查找表, n表长, k关键字*/ int i; for (i=0; in; i+) if (k=ai) return (i+1); return 0

2、; void main()int x,t,a9=10,31,12,42,35,76,16,18,29,; scanf(%d,&x);t=search(a,9,x);if (t=0) printf(Not found!n);else printf(%dn,t); ./改进的顺序查找#includeint search (int a, int n, int k) /*a查找表, n表长, k关键字*/ int i=n; a0=k; while (ai!=k) i-; return i; void main()int a10=0,10,31,12,42,35,76,16,18,29,;int x,t

3、;scanf(%d,&x);t=search(a,9,x);if (t=0) printf(Not found!n);else printf(%dn,t); .二、折半(二分)查找基本思想: 如果查找表中的数据元素按关键字有序(假设递增有序),则在查找时,可不必逐个顺序比较,而采用跳跃的方式先与“中间位置”的数据元素关键字比较,若相等,则查找成功;若给定值大于“中间位置”的关键字,则在查找表的后半部继续进行二分查找,否则在前半部进行二分查找。 算法特点:仅适用于以顺序存储结构组织有序表的查找。.先确定待查元素所在区域,然后逐步缩小区域,直到查找成功或失败为止。 假设:待查元素所在区域的下界为l

4、ow,上界为hig,则中间位置mid=(low+hig)/2 1、若此元素关键字值等于给定值,则查找成功 2、若此元素关键字值大于给定值,则在区域 (mid+1)与high 内进行二分查找 3、若此元素关键字值小于给定值,则在区域low与(mid-1) 内进行二分查找./非递归算法int bin_search (int a , int n, int k) int low, high, mid; low=0; high=n-1; while (low = high) mid=(low + high)/2; if (k amid) low = mid + 1;else return mid ; r

5、eturn -1;./递归算法int bin_search (int a , int low,int high ,int k)int mid=(low + high)/2;if ( lowhigh) return -1;else if (k = amid) return mid; else if (k amid ) bin_search(a,mid+1,high,k); else bin_search(a,low,mid-1,k) ; .例1、2006年湖南人文科技学院预赛试题给定整数 a1,a2,a3,an(其中有负数),求整数中的最大子序列和。为了方便起见,如果所有整数为负数,则最大子序列

6、和为0。例如:对于-2、11、-4、13、-5、-2,最大子序列和为20(11-4+13)。 方法1:二分法,时间复杂度为O(nlog2n)其余方法详见: 程序设计培训讲义7:数组.#include #define N 100int aN=-2,11,-4,13,-5,-2;int max3(int x,int y,int z)int m;m=xy ? x:y;return mz ? m :z;void main()int maxsub(int a,int left,int right);printf(Maxsub=%dn,maxsub(a,0,3); .int maxsub(int a ,i

7、nt left,int right)int i,mid,maxleft,maxright,m1,m2,max1,max2;if (left=right) if (aleft0) return aleft; else return 0;mid=(left+right)/2;maxleft=maxsub(a,left,mid);maxright=maxsub(a,mid+1,right);for (m1=0,max1=0,i=mid; i=left; i-)m1=m1+ai;if ( m1 max1 ) max1=m1; for (m2=0,max2=0,i=mid+1; i max2 ) max

8、2=m2; return max3(maxleft,maxright,max1+max2);.三、排序算法分类 插入排序类直接插入排序、折半插入排序、希尔排序选择排序类直接选择排序、树型选择排序、堆排序交换排序类冒泡排序(称直接交换排序)、快速排序 归并排序类二路归并四、非递归排序算法.1、插入排序 把n个数据元素的序列分成两部分: R1, ., Ri-1为已排好序的有序部分 Ri, Ri+1, ., Rn 为未排序部分 把未排序部分的第1个元素Ri依次与R1, ., Ri-1比较,并插入到有序部分的合适位置上,使得 R1, ., Ri 变为新的有序部分。 初始时,令i=2。因为一个元素自然有

9、序,故R1 自然成为一个有序部分,未排序部分是R2, ., Rn,然后依次将R2, R3, ., Rn插入到有序部分中去,就可得整个有序序列.初始关键字: 49 38 65 97 76 13 27 49i=2: 38 49 65 97 76 13 27 49i=3: 38 49 65 97 76 13 27 49i=4: 38 49 65 97 76 13 27 49i=6: 13 38 49 65 76 97 27 49i=7: 13 27 38 49 65 76 97 49i=8: 13 27 38 49 49 65 76 97i=5: 38 49 65 76 97 13 27 49无序有

10、序.void insert(int a ,int n)/对数组a中的元素a1、a2an 排序int i,j;for (i=2; i=n; i+) if ( aiai-1 ) a0=ai;j=i-1;while (a0=1) for (i=d+1; i0 & a0aj) aj+d=aj; j=j-d; aj+d=a0; d=d/2;.3、直接选择排序第一趟排序是在无序的R1, R2, R3, ., Rn按排序码选出最小的元素,将它与R1交换。第二趟排序是在无序的R2, R3, ., Rn中选出最小的元素,将它与R2交换。第i趟排序时R1, R2, R3, ., Ri-1已排好序,在当前无序的Ri

11、, ., Rn中再选出最小的元素,将它与Ri元素交换,使R1, R2, R3, ., Ri成为有序 经过n-1趟排序后,整个数据元素序列就递增有序。./直接选择排序/对数组a中的元素a0、a1an-1 排序void sort(int a ,int n)int i, j, t, min;for (i=0; in-1; i+) min=i;/ 寻找当前最小元素的下标存入min for (j=i+1; jn;j+)if ( ajamin ) min=j; t=amin; amin=ai; ai=t; .4、冒泡排序 (直接交换排序) 第一趟每次进行相邻两个元素关键字的比较,如不符合次序立即交换,这样

12、关键值大的(或小的)就会象冒气泡一样逐步升起。 算法思想: 先将rn与rn-1比较,若rnrn-1则互相交换。 再比较rn-1和rn-2,依次类推,直到rt与r1比较(交换)把关键字较小的记录移至最前,完成一趟排序。 然后对余下的r(2)r(n)的n-1个记录重复上述操作。./冒泡排序1:大数向后移/对数组a中的元素a0、a1an-1 排序void sort(int a ,int n)int i, j, t;/大数向后移,外循环一次,/将当前的最大数移到a10-i上for (i=0; in-1; i+) for (j=0; jaj+1 ) t=aj; aj=aj+1; aj+1=t; ./冒泡

13、排序2:小数向前移/对数组a中的元素a0、a1an-1 排序void sort(int a ,int n)int i, j, t;/ 小数向前移,外循环一次/ 将当前的最小数移到ai上for (i=0; in-1; i+) for (j=i+1; jn;j+) if ( ajai ) t=aj; aj=ai; ai=t; ./冒泡排序3:改进的冒泡排序/对数组a中的元素a0、a1an-1 排序void sort(int a ,int n)int i, j, t,bz=1;for (i=0; in-1 & bz; i+) bz=0; /表示不需要继续排序 for (j=0; jaj+1 ) t=

14、aj; aj=aj+1; aj+1=t; bz=1; /*存在交换,需要继续排序*/ ./冒泡排序4:改进的冒泡排序/对数组a中的元素a0、a1an-1 排序void sort(int a ,int n)int k,j,t,m=n-1;while ( m0 )/小数向前移,将当前的最小数移到ai上 for (k=j=0; jaj+1 ) t=aj; aj=aj+1; aj+1=t; k=j; /记下最后一次交换的元素的下标 到km=k; /也可以为 m=m-1 .5、快速排序快速排序又称分区交换排序,是对冒泡排序的一种改进,是目前内部排序中比较快的方法。它通过分步排序来完成整个表的排序。这种方

15、法的每一步都把要排序表的第一个元素(或者是中间位置的元素)放到它在表中的最终位置,同时在这个元素的前面和后面各形成一个子表。在前子表中的所有元素的关键字都比该元素的关键字小,而在后子表中的都比它大。此后再对每个子表做同样的操作,直到最后每个子表都只有一个元素,排序结束.初始关键字序列:49 38 65 97 76 13 27 4949 38 65 97 76 13 27 4927 38 65 97 76 13 49 4927 38 49 97 76 13 65 4927 38 13 97 76 49 65 4927 38 13 49 76 97 65 49i1j1ij1i1i1j1i1j1i1

16、j1i1j1./快速排序1:以第1个元素来分区间/对数组a中的元素aleft、aleft+1aright 排序void sort(int a ,int left, int right) int i,j,t; i=left ; j=right; t=ai; do while ( t=aj & ij ) j-; /从后向前搜索 if ( ij ) ai=aj; i+; while ( ai=t & ij ) i+; /从前向后搜索 if ( ij ) aj=ai; j-; while (i!=j);ai=t; /把t即最先的ai放到此次的适当位置if ( lefti ) qsort(a,i+1,r

17、ight); /排序后半部分./快速排序2:以中间元素来分区间/对数组a中的元素aleft、aleft+1aright 排序void sort(int a ,int left, int right) int i,j,x,y;i=left ; j=right; x=a(left+right)/2; /用中间元素 do while ( aix & ix & jleft ) j-; /找一个比x小的元素aj if ( i=j ) y=aj;aj=ai; ai=y; i+; j-; while (i=j); if ( lefti ) sort(a,i+1,right);/排序后半部分.6、归并排序(表

18、排序)归并的含义是把两个(或两个以上)有序的序列合并为一个有序的序列。将有n个元素的原始序列看作n个有序子序列,每个子序列的长度为1然后从第一个子序列开始,把相邻的子序列两两合并,得到n/2个长度为2或1的子序列,这一过程称为一次归并排序。对第一次归并排序后的n/2个子序列采用上述方法,继续顺序归并,如此重复,当最后得到长度为n的一个子序列时,该子序列便是原始序列归并排序后的有序序列。.void merge(int r ,int r1 ,int low,int m,int h) /*rlow.m及rm+1.h分别有序,归并后置于r1中*/int i=low,j=m+1,k=low; /*i和j

19、是r的指示器*/ /*i的取值从l到m,j的取值从m+1到h;k是r1的指示器*/while (i=m & j=h)if (rim) /*前部分结束*/while (j=h) /*将后部分复制到r1*/r1k=rj; j+; k+;else /*后部分结束*/while (i2*len)merge(r,r1,p,p+len-1,p+2*len-1);p+=2*len; /p向后移动2*l,准备下一次合并if (n-p+1len) /一个长度为len的部分与一个长度小于len的部分合并merge(r,r1,p,p+len-1,n);else /只剩下一个长度不大于len的部分,将其复制到r1fo

20、r (;p=n;p+) r1p=rp;.void mergesort(int r,int r1,int n)/*对r中数据元素进行归并,结果仍放在r中*/int len=1;while (lenn)mergepass(r,r1,n,len);len*=2; /*从r归并到r1*/mergepass(r1,r,n,len);len*=2; /*从r1归并到r*/void main()int a11=0,75,87,68,92,88,61,77,96,80,72;/*a0元素不计入元素个数*/int a110, n=10,i;mergesort(a,a1,n);for (i=1;i=n;i+)pr

21、intf(%6d,ai); . 归并排序的非递归算法2:void merge(int r ,int r1 ,int low,int m,int h) /*rlow.m及rm+1.h分别有序,归并后置于r1中*/int i=low,j=m+1,k=low; while (i=m & j=h)if (rim) /*前部分结束*/while (j=h) /*将后部分复制到r1*/r1k=rj; j+; k+;else /*后部分结束*/while (i=m) /*将前部分复制到r1*/r1k=ri; i+; k+;for (i=low; i=h; i+)ri=r1i;返回递归函数.void sort

22、(int a ,int b ,int n) /自底向上排序/ 将数组a0,a1, an-1排序/ 利用数组b 过渡,b与a的长度相等int i,len;len=1;while ( lenn )i=0;while ( i+2*len=n )merge(a,b,i,i+len-1,i+2*len-1);i=i+2*len; if ( i+lenn )merge(a,b,i,i+len-1,n-1);len=len*2;.7、堆排序利用完全二叉树对数组排序: 1、将一个无序序列建成堆, 2、输入出顶点元素后,调整并重建堆, 3、重复2直至全部元素都输出完毕。.void sift(int p ,int

23、 i,int n)/调整数组p的第i元素,n为数组长度 int j,t; t=pi; j=2*(i+1)-1; /左子树 while(j=n) if ( (jn) & (pjpj+1) ) j+; /右子树 if( t=0;i-) /初始建堆 sift(p,i,n-1); for(i=n-1;i=1;i-) /重建堆 t=p0; p0=pi; pi=t; sift(p,0,i-1); void main( ) int i, a10=75,87,68,92,88,61,77,96,80,72; sort(a,10); for(i=0;i10;i+) printf(%d,ai);.五、递归排序算法1、选择排序的递归算法/对数组a中的元素

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论