信息学竞赛常用算法与策略:排序 标签:信息学
<p><strong>优学合肥奥数网讯:信息学竞赛常用算法与策略:排序</strong>。</p><p>排序就是将杂乱无章的数据元素,通过一定的方法按关键字顺序排列的过程。</p><p><strong>4.1 简单排序</strong></p><p>1.选择排序</p><p>选择排序的基本思想是:</p><p>对待排序的记录序列进行n-1遍的处理,第1遍处理是将L中最小者与L交换位置,第2遍处理是将L中最小者与L交换位置,......,第i遍处理是将L中最小者与L交换位置。这样,经过i遍处理之后,前i个记录的位置就已经按从小到大的顺序排列好了。</p><p>例1:输入序列数据按非减顺序输出.</p><p>程序如下:</p><p>program xzpx;</p><p>const n=7;</p><p>var a:array of integer;</p><p>i,j,k,t:integer;</p><p>begin</p><p>write('Enter date:');</p><p>for i:= 1 to n do read(a);</p><p>writeln;</p><p>for i:=1 to n-1 do</p><p>begin</p><p>k:=i;</p><p>for j:=i+1 to n do</p><p>if a<a then k:=j;</p><p>if k<>i then</p><p>begin t:=a;a:=a;a:=t;end;</p><p>end;</p><p>write('output data:');</p><p>for i:= 1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>2.插入排序</p><p>插入排序的基本思想:经过i-1遍处理后,L己排好序。第i遍处理仅将L插入L的适当位置p,原来p后的元素一一向右移动一个位置,使得L又是排好序的序列。</p><p>例2:输入序列数据按非减顺序输出.</p><p>程序1:</p><p>program crpx;</p><p>const n=7;</p><p>var a:array of integer;</p><p>i,j,k,t:integer;</p><p>begin</p><p>write('Enter date:');</p><p>for i:= 1 to n do read(a);</p><p>writeln;</p><p>for i:=2 to n do</p><p>begin</p><p>k:=a;j:=i-1;</p><p>while (k<a) and (j>0) do</p><p>begin a:=a;j:=j-1 end;</p><p>a:=k;</p><p>end;</p><p>write('output data:');</p><p>for i:= 1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>3.冒泡排序</p><p>冒泡排序又称交换排序其基本思想是:对待排序的记录的关键字进行两两比较,如发现两个</p><p>记录是反序的,则进行交换,直到无反序的记录为止。</p><p>例:输入序列数据按非减顺序输出。</p><p>程序1:</p><p>program mppx;</p><p>const n=7;</p><p>var a:array of integer;</p><p>i,j,k,t:integer;</p><p>begin</p><p>write('Enter date:');</p><p>for i:= 1 to n do read(a);</p><p>for i:=1 to n -1 do</p><p>for j:=n downto i+1 do</p><p>if a<a then</p><p>begin t:=a;a:=a;a:=t end;</p><p>write('output data:');</p><p>for i:= 1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>程序2:</p><p>program mppx;</p><p>const n=7;</p><p>var a:array of integer;</p><p>i,j,k,t:integer;</p><p>bool:boolean;</p><p>begin</p><p>write('Enter date:');</p><p>for i:= 1 to n do read(a);</p><p>i:=1;bool:=true;</p><p>while (i<n) and bool do</p><p>begin</p><p>bool:=false;</p><p>for j:=n downto i+1 do</p><p>if a<a then</p><p>begin t:=a;a:=a;a:=t;bool:=true end;</p><p>i:=i+1;</p><p>end;</p><p>write('output data:');</p><p>for i:= 1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>程序3:</p><p>program mppx;</p><p>const n=7;</p><p>var a:array of integer;</p><p>i,j,k,t:integer;</p><p>begin</p><p>write('Enter date:');</p><p>for i:= 1 to n do read(a);</p><p>writeln;</p><p>k:=n;</p><p>while k>0 do</p><p>begin</p><p>j:=k-1;k:=0;</p><p>for i:=1 to j do</p><p>if a>a then</p><p>begin t:=a;a:=a;a:=t;k:=i;end;</p><p>end;</p><p>write('output data:');</p><p>for i:= 1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p><strong>4.2快速排序</strong></p><p>快速排序的思想是:先从数据序列中选一个元素,并将序列中所有比该元素小的元素都放到它的右边或左边,再对左右两边分别用同样的方法处之直到每一个待处理的序列的长度为1, 处理结束.</p><p>例:输入一组数据小到大排序.</p><p>程序1:</p><p>program kspv;</p><p>const n=7;</p><p>type</p><p>arr=array of integer;</p><p>var</p><p>a:arr;</p><p>i:integer;</p><p>procedure quicksort(var b:arr; s,t:integer);</p><p>var i,j,x,t1:integer;</p><p>begin</p><p>i:=s;j:=t;x:=b;</p><p>repeat</p><p>while (b>=x) and (j>i) do j:=j-1;</p><p>if j>i then begin t1:=b; b:=b;b:=t1;end;</p><p>while (b<=x) and (i<j) do i:=i+1;</p><p>if i<j then begin t1:=b;b:=b;b:=t1; end</p><p>until i=j;</p><p>b:=x;</p><p>i:=i+1;j:=j-1;</p><p>if s<j then quicksort(b,s,j);</p><p>if i<t then quicksort(b,i,t);</p><p>end;</p><p>begin</p><p>write('input data:');</p><p>for i:=1 to n do read(a);</p><p>writeln;</p><p>quicksort(a,1,n);</p><p>write('output data:');</p><p>for i:=1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>程序2:</p><p>program kspv;</p><p>const n=7;</p><p>type</p><p>arr=array of integer;</p><p>var</p><p>a:arr;</p><p>i:integer;</p><p>procedure quicksort(var b:arr; s,t:integer);</p><p>var i,j,x:integer;</p><p>begin</p><p>i:=s;j:=t;x:=b;</p><p>repeat</p><p>while (b>=x) and (j>i) do j:=j-1;</p><p>if j>i then beginb:=b;i:=i+1;end;</p><p>while (b<=x) and (i<j) do i:=i+1;</p><p>if i<j then begin b:=b;j:=j-1; end</p><p>until i=j;</p><p>b:=x;</p><p>i:=i+1;j:=j-1;</p><p>if s<j then quicksort(b,s,j);</p><p>if i<t then quicksort(b,i,t);</p><p>end;</p><p>begin</p><p>write('input data:');</p><p>for i:=1 to n do read(a);</p><p>writeln;</p><p>quicksort(a,1,n);</p><p>write('output data:');</p><p>for i:=1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p><strong>4.3希尔排序</strong></p><p>基本思想:将整个无序序列分割成若干小的子序列分别进行插入排序或冒泡排序。</p><p>序列分割方法:将相隔某个增量h的元素构成一个子序列。在排序过程中,逐次减小这个增量,最后当h减到1时,进行一次插入排序或冒泡排序,排序就完成。增量序列一般采用:d1=n div 2 ,di=di-1 div 2 ;i=2,3,4.....其中n为待排序序列的长度。</p><p>程序1:(子序列是插入排序)</p><p>program xepx;</p><p>const n=7;</p><p>type</p><p>arr=array of integer;</p><p>var</p><p>a:arr;</p><p>i,j,t,d:integer;</p><p>bool:boolean;</p><p>begin</p><p>write('input data:');</p><p>for i:=1 to n do read(a);</p><p>writeln;</p><p>d:=n;</p><p>while d>1 do</p><p>begin</p><p>d:=d div 2;</p><p>for j:=d+1 to n do</p><p>begin</p><p>t:=a;i:=j-d;</p><p>while (i>0) and (a>t) do</p><p>begin a:=a;i:=i-d;end;</p><p>a:=t;</p><p>end;</p><p>end;</p><p>write('output data:');</p><p>for i:=1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p>程序2:(子序列是冒泡排序)</p><p>program xepx;</p><p>const n=7;</p><p>type</p><p>arr=array of integer;</p><p>var</p><p>a:arr;</p><p>i,temp,d:integer;</p><p>bool:boolean;</p><p>begin</p><p>write('input data:');</p><p>for i:=1 to n do read(a);</p><p>writeln;</p><p>d:=n</p><p>while d>1 do</p><p>begin</p><p>d:=d div 2;</p><p>repeat</p><p>bool:=true;</p><p>for i:=1 to n-d do</p><p>if a>a then</p><p>begin temp:=a;a:=a;a:=temp; bool:=false end;</p><p>until bool;</p><p>end;</p><p>write('output data:');</p><p>for i:=1 to n do write(a:6);</p><p>writeln;</p><p>end.</p><p><strong>4.4 堆排序与二叉树排序</strong></p><p>1.堆排序</p><p>堆:设有数据元素的集合(R1,R2,R3,...Rn)它们是一棵顺序二叉树的结点且有</p><p>Ri<=R2i 和Ri<=R2i+1(或>=)</p><p>堆的性质:堆的根结点上的元素是堆中的最小元素,且堆的每一条路径上的元素都是有序的。</p><p>堆排序的思想是:</p><p>1)建初始堆(将结点,[ n/2]-1,...3,2,1分别调成堆)</p><p>2)当未排序完时</p><p>输出堆顶元素,删除堆顶元素,将剩余的元素重新建堆。</p><p>程序如下:</p><p>program duipx;</p><p>const n=8;</p><p>type arr=array of integer;</p><p>var a:arr;i:integer;</p><p>procedure sift(var a:arr;l,m:integer);</p><p>var i,j, t:integer;</p><p>begin</p><p>i:=l;j:=2*i;t:=a;</p><p>while j<=m do</p><p>begin</p><p>if (j<m) and (a>a) then j:=j+1;</p><p>if t>a then</p><p>begin a:=a;i:=j;j:=2*i; end</p><p>else exit;</p><p>a:=t;</p><p>end;</p><p>end;</p><p>begin</p><p>for i:=1 to n do read(a);</p><p>for i:=(n div 2) downto 1 do</p><p>sift(a,i,n);</p><p>for i:=n downto 2 do</p><p>begin</p><p>write(a:4);</p><p>a:=a;</p><p>sift(a,1,i-1);</p><p>end;</p><p>writeln(a:4);</p><p>end.</p><p>2.二叉树排序</p><p>排序二叉树:每一个参加排列的数据对应二叉树的一个结点,且任一结点如果有左(右)子树,则左(右)子树各结点的数据必须小(大)于该结点的数据。中序遍历排序二叉树即得排序结果。程序如下:</p><p>program pxtree;</p><p>const</p><p>a:array of integer=(10,18,3,8,12,2,7,3);</p><p>type point=^nod;</p><p>nod=record</p><p>w:integer;</p><p>right,left:point ;</p><p>end;</p><p>var root,first:point;k:boolean;i:integer;</p><p>procedure hyt(d:integer;var p:point);</p><p>begin</p><p>if p=nil then</p><p>begin</p><p>new(p);</p><p>with p^ do begin w:=d;right:=nil;left:=nil end;</p><p>if k then begin root:=p; k:=false end;</p><p>end</p><p>else with p^ do if d>=w then hyt(d,right) else hyt(d,left);</p><p>end;</p><p>procedure hyt1(p:point);</p><p>begin</p><p>with p^ do</p><p>begin</p><p>if left<>nil then hyt1(left);</p><p>write(w:4);</p><p>if right<>nil then hyt1(right);</p><p>end</p><p>end;</p><p>begin</p><p>first:=nil;k:=true;</p><p>for i:=1 to 8 do hyt(a,first);</p><p>hyt1(root);writeln;</p><p>end.</p><p><strong>4.5 归并排序</strong></p><p>归并就是将多个有序的数列合成一个有序的数列。将两个有序序列合并为一个有序序列叫二路归并(merge).归并排序就是n长度为1的子序列,两两归并最后变为有序的序列。</p><p>1.二路归并</p><p>例1:将有序表L1=(1,5,7),L2=(2,3,4,6,8,9,10)合并一个有序表 L.</p><p>program gb;</p><p>const m=3;n=7;</p><p>type arrl1=array of integer;</p><p>arrl2=array of integer;</p><p>arrl=array of integer;</p><p>var a:arrl1;</p><p>b:arrl2;</p><p>c:arrl;</p><p>i,j,k,r:integer;</p><p>begin</p><p>write('Enter l1(sorted):');</p><p>for i:=1 to m do read(a);</p><p>write('Enter l2(sorted):');</p><p>for i:=1 to n do read(b);</p><p>i:=1;j:=1;k:=0;</p><p>while (i<=m) and (j<=n) do</p><p>begin</p><p>k:=k+1;</p><p>if a<=b then begin c:=a;i:=i+1; end</p><p>else begin c:=b;j:=j+1;end;</p><p>end;</p><p>if i<=m then for r:=i to m do c:=a;</p><p>if j<=n thenfor r:=j to n do c:=b;</p><p>writeln('Output data:');</p><p>for i:=1 to m+n do write(c:5);</p><p>writeln;</p><p>end.</p><p>2.归并排序</p><p>program gbpx;</p><p>const maxn=7;</p><p>type arr=array of integer;</p><p>var a,b,c:arr;</p><p>i:integer;</p><p>procedure merge(r:arr;l,m,n:integer;var r2:arr);</p><p>var i,j,k,p:integer;</p><p>begin</p><p>i:=l;j:=m+1;k:=l-1;</p><p>while (i<=m)and (j<=n) do</p><p>begin</p><p>k:=k+1;</p><p>if r<=r then begin r2:=r;i:=i+1 end</p><p>else begin r2:=r;j:=j+1 end</p><p>end;</p><p>if i<=m then</p><p>for p:=i to m do begin k:=k+1;r2:=r end;</p><p>if j<=n then</p><p>for p:=j to n do begin k:=k+1;r2:=r end;</p><p>end;</p><p>procedure mergesort( var r,r1:arr;s,t:integer);</p><p>var k:integer; c:arr;</p><p>begin</p><p>if s=t then r1:=r else</p><p>begin</p><p>k:=(s+t) div 2;</p><p>mergesort(r,c,s,k);</p><p>mergesort(r,c,k+1,t);</p><p>merge(c,s,k,t,r1)</p><p>end;</p><p>end;</p><p>begin</p><p>write('Enter data:');</p><p>for i:= 1 to maxn do</p><p>read(a);</p><p>mergesort(a,b,1,maxn);</p><p>for i:=1 to maxn do</p><p>write(b:9);</p><p>writeln;</p><p>end.</p><p>4.6 线形排序</p><p>以上我们讨论的算法均是基于比较的排序算法,在排序算法中有基于数字本身的算法:计数、桶、基数排序。</p><p>1.计数排序</p><p>基本思想是对于序列中的每一元素x,确定序列中小于x的元素的个数。</p><p>例:n个整数序列且每个值在,排序之。</p><p>program jspx;</p><p>const m=6;n=8;</p><p>var i,j:integer;</p><p>a,b:array of integer;</p><p>c:array of integer;</p><p>begin</p><p>writeln('Enter data:');</p><p>for i:=1 to n do read(a);</p><p>for i:=1 to m do c:=0;</p><p>for i:=1 to n do c]:=c]+1;</p><p>for i:=2 to m do c:=c+c;</p><p>for i:=n downto 1 do</p><p>begin</p><p>b]]:=a;</p><p>c]:=c]-1;</p><p>end;</p><p>writeln('Sorted data:');</p><p>for i:= 1 to n do</p><p>write(b:6);</p><p>end.</p><p>2.桶排序</p><p>桶排序的思想是若待排序的记录的关键字在一个明显有限范围内(整型)时,可设计有限个有序桶,每个桶装入一个值,顺序输出各桶的值,将得到有序的序列。</p><p>例:输入n个0到100之间的整数,由小到大排序输出。</p><p>program tpx;</p><p>const n=7;</p><p>var b:array of integer;</p><p>k:0..100;</p><p>i:integer;</p><p>begin</p><p>write('Enter date:(0-100)');</p><p>for i:=0 to 100 do b:=0;</p><p>for i:= 1 to n do</p><p>begin</p><p>read(k);</p><p>b:=b+1;</p><p>end;</p><p>writeln('Output data:');</p><p>for i:=0 to 100 do</p><p>while b>0 do begin write(i:6);b:=b-1 end;</p><p>writeln;</p><p>end.</p><p>3.基数排序</p><p>基本思想是对n个元素依次按k,k-1,...1位上的数字进行桶排序。</p><p>program jspx;</p><p>const n=8;</p><p>type link=^node;</p><p>node=record</p><p>data:integer;</p><p>next:link;</p><p>end;</p><p>var i,j,l,m,k:integer;</p><p>a:array of integer;</p><p>s:string;</p><p>q,head:array of link;</p><p>p,p1:link;</p><p>begin</p><p>writeln('Enter data:');</p><p>for i:=1 to n do read(a);</p><p>for i:=5 downto 1 do</p><p>begin</p><p>for j:=0 to 9 do</p><p>begin</p><p>new(head);</p><p>head^.next:=nil;</p><p>q:=head</p><p>end;</p><p>for j:=1 to n do</p><p>begin</p><p>str(a,s);</p><p>for k:=1 to 5-length(s) do</p><p>s:='0'+ s;</p><p>m:=ord(s)-48;</p><p>new(p);</p><p>p^.data:=a;</p><p>p^.next:=nil;</p><p>q^.next:=p;</p><p>q:=p;</p><p>end;</p><p>l:=0;</p><p>for j:=0 to 9 do</p><p>begin</p><p>p:=head;</p><p>while p^.next<>nil do</p><p>begin</p><p>l:=l+1;p1:=p;p:=p^.next;dispose(p1);a:=p^.data;</p><p>end;</p><p>end;</p><p>end;</p><p>writeln('Sorted data:');</p><p>for i:= 1 to n do</p><p>write(a:6);</p><p>end.</p><p><strong>4.7各种排序算法的比较</strong></p><p>1.稳定性比较</p><p>插入排序、冒泡排序、二叉树排序、二路归并排序及其他线形排序是稳定的</p><p>选择排序、希尔排序、快速排序、堆排序是不稳定的</p><p>2.时间复杂性比较</p><p>插入排序、冒泡排序、选择排序的时间复杂性为O(n2)</p><p>其它非线形排序的时间复杂性为O(nlog2n)</p><p>线形排序的时间复杂性为O(n);</p><p>3.辅助空间的比较</p><p>线形排序、二路归并排序的辅助空间为O(n),其它排序的辅助空间为O(1);</p><p>4.其它比较</p><p>插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。</p><p>反而在这种情况下,快速排序反而慢了。</p><p>当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序。</p><p>若待排序的记录的关键字在一个明显有限范围内时,且空间允许是用桶排序。</p><p>当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。</p><p>当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下。</p><p>宜用归并排序。</p><p>当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。</p><p>关于合肥市青少年信息学竞赛更多的信息,请关注优学合肥奥数网“<strong>青少年信息学竞赛</strong>”频道。</p><p>信息学竞赛常用算法与策略:回溯</p><p>信息学竞赛常用算法与策略:递归</p><p>信息学竞赛常用算法与策略:算法的概念</p><p>青少年信息学竞赛Pascal语言:程序调试(十一)</p><p><strong>更多精彩内容推荐>></strong></p>
页:
[1]