排序模板

      简单地复习一下排序,虽然说常用的只有几种但还是把所有的排序都复习一下,所有算法的存在都有它的理由,也都承载着许多人的智慧,再理解一遍对OI的学习或许有一些启发作用。

pascal模板

冒泡排序

      最早学习的就是冒泡学习,原理最简单,当然速度也是最慢的,不过在一些特殊的题型中会有一些独有的作用,首先,是它的交换原理的应用,比如一些只能左右交换的数据就只可以用冒泡排序,题目就像熟知的车厢重组求步数,是非冒泡排序不可的。在冒泡的过程中,一定要注意记录当前循环是否发生交换,如果无则结束,也算一个剪枝吧:

i:=1
 repeat
   bo:=true;
   for  j:=1 to n-i do
   if a[j]<a[j+1] then
   begin
     t:=a[i];  a[i]:=a[j];  a[j]:=t;
     bo:=false;
   end;  
   inc(i);
 until bo; 

快速排序

      快排是最常用的一种算法,要掌握多关键字的快排和有主次之分的快排,用random来防止排序退化,然后注意一些小技巧即可。注意主程序里的randomize不要忘记:

procedure qsort(l,r:longint);
var
  i,j,k,mid:longint;
begin
  i:=l; j:=r;
  mid:=a[l+random(r-l+1)];
  repeat
    while a[i]<mid do inc(i);
    while a[j]>mid do dec(j);
    if i<=j then
    begin
      k:=a[i];
      a[i]:=a[j];
      a[j]:=k;
      inc(i); dec(j);
    end;
  until i>j;
  if i<r then qsort(i,r);
  if l<j then qsort(l,j);
end;

桶排序

      从原理上来说,桶排序是最快的一种排序,但是由于其内存开销太大了,所以从实用性上比较起来是比较弱的,但是这种思想还是很重要的,当然,数据规模不大时,桶排序还是很实用的。 

For i:=1 to m do b[i]:=0;   //m是数据范围
  For i:=1 to n do
  Begin
      Read(k);
      B[k]:=b[k]+1;
  End;
For i:=1 to m do
While b[i]>0 do begin
    Write(I,’ ‘);
    Dec(b[i]);
End;

插入排序

      这是一种比较慢的方法,主要思想是设置一个负无穷大的数,不断插入新的数,将后面的数后移一位,开始学习的时候受书上的误导,在原数组上操作,导致每插入一个数整个数组后移,奇慢,唉,尽信书不如无书啊,不过这个算法代码没多少复习必要,思想温习一下即可。还有熟练这种思想在有序链表上的运用,在hash表上还是比较常用的。

归并排序

      将多路有序数列合并,主要是比较麻烦,如果要可排序的话,可并堆会更优秀一些,但是这毕竟也可以和快排相媲美了

Procedure mergerort(s,t:longint);
Var
  M,I,j,k:longint;
Begin
  If s=t then exit;
  M:=(s+t)>>1;
  Mergesort(s,m);
  Mergesort(m+1,t);
  I:=s;
  J:=m+1;
  K:=s;
  While (i<=m)and(j<=t) do
  Begin
    If a[i]<a[j] then
       Begin
          R[k]:=a[i];
          Inc(i); inc(k);
       End
       Else begin
         R[k]:=a[j];
         Inc(j);
          Inc(k);
      End;
      While i<m do
      begin
         r[k]:=a[i]; inc(i); inc(k); 
      end;
      while j<=t do
      begin
        r[k]:=a[j]; inc(j); inc(k);
      end;
  for i:=s to t do
  remove(r[i],a[i],sizeof(r[i]));
end; 

基数排序

      基数排序比桶排略慢,但是内存消耗却比桶排序要节省许多,就是字符串处理比较麻烦,不过,也不失为一种比较好的算法:

var
  max,i,j,k,m,n:longint;
  x:array['0'..'9',1..100000] of ansistring;
  a:array[1..100000] of ansistring;
  l:array['0'..'9'] of longint;
  c:char;

begin
  readln(n);
  for i:=1 to n do
  begin
    readln(a[i]);
    if length(a[i])>max then max:=length(a[i]);
  end;
  for i:=1 to n do
  while length(a[i])<max do a[i]:='0'+a[i];
  for j:=max downto 1 do
  begin
    for c:='0' to '9' do l[c]:=0;
    for i:=1 to n do
    begin
      inc(l[a[i][j]]);
      x[a[i][j],l[a[i][j]]]:=a[i];
    end;
    m:=0;
    for c:='0' to '9' do
    for i:=1 to l[c] do
    begin
      inc(m);
      a[m]:=x[c,i];
    end;
  end;
  for i:=1 to n do
  begin
    for j:=1 to length(a[i]) do
    if a[i][j]<>'0' then
    begin
      for k:=j to length(a[i]) do
      write(a[i][k]);
      writeln;
      break;
    end;
  end;
end.

      单纯排序的似乎没有什么特别难的题目,但是经过组合,许多时候,巧妙地运用排序,比如优化二分或是优化搜索,可以提高程序效率,蒽,就这样吧,好好理解一下。

愿你出走半生,归来仍是少年

原文地址:https://www.cnblogs.com/forever97/p/3427594.html