第八章 排序技术

来源:互联网 发布:淘宝网如何投诉卖家 编辑:程序博客网 时间:2024/06/05 05:36


8排序技术

8.1概述

在排序问题中,通常将数据元素成为记录。

若待排序序列中的记录已按关键码排好序,称此记录序列为正序;若待排序序列中记录的排列顺序与排好序的顺序正好相反,称此记录序列为逆序或反序。

排序的分类

内排序是指在排序的整个过程中,待排序的所有记录全部被放在内存中;外排序是指由于待排序的记录个数太多,不能同时放置在内存,而需要将一部分记录放置在内存,另一部分记录放置在外存。

可以将平排序方法分为基于比较的排序和不基于比较的排序。

8.2插入排序

8.2.1直接插入排序

直接插入排序是插入排序中最简单的排序方法,类似于玩纸牌是整理手中纸牌的过程。

直接插入排序算法InsertSort

void InsertSort{int r[],int n}

{

      for(i=2;i<=n;i++)

      {

             r[0]=r[i];

             for(j=i-1;r[0]<r[j];j--)

                    r[j+1]=r[j];

             r[j+1]=r[0];

      }

}

8.2.2希尔排序

希尔排序的基本思想是:先将整个待排序记录序列分割成若干个子序列,在子序列内分别进行直接插入排序,待整个序列基本有序时,在对全体记录进行一次直接插入排序。

希尔排序算法ShellSort

void ShellSort(int r[],int n)

{

      for(d=n/2;d>=1;d=d/2)

      {

             for(i=d+1:i<=n;i++)

             {

                    r[0]=r[i];

                    for(j=i-d;j>0&&r[0]<r[j];j=j-d)

                           r[j+d]=r[0];

             }

      }

}

8.3交换排序

8.3.1起泡排序

起泡排序是交换排序中最简单的排序方法,其基本思想是两辆比较相邻记录的关键码,如果反序则交换,直到没有反序的记录为止。

起泡排序算法BubbleSort

void BubbleSort(intr[],int n)

{

   exchange=n;

   while (exchange!=0)

   {

       bound=exchange;exchange=0;

       for(j=1;j<bound;j++)

           if(r[j]>r[j+1]){

               r[j]←→r[j+1];

               exchange=j;

           }

   }

}

8.3.2快速排序

快速排序是对起泡排序的一种改进,改进的着眼点是:在起泡排序中,记录的比较和移动是在相邻位置进行的,记录每次交换只能后移一个位置,因而总的比较次数和移动次数较多

选择轴值有多种方法,最简单的方法是选取第一个记录的关键码,还可以选取中间记录的关键码,或者在每次划分之前比较待排序序列的第一个记录,最后一个记录和中间记录的关键码,选取居中的关键码作为轴值并调换到第一个记录的位置。

一次划分的过程为

1初始化

2右侧扫描过程

3左侧扫描过程

4重复2 3步,直到ij指向同一位置,即轴值记录的最终的位置。

快速排序一次划分算法Partition

int Partition(intr[],int first,int end)

{

   i=first;j=end;

   while(i<j)

   {

       while(i<j&&r[i]<=r[j])j--;

       if(i<j){

           r[i]←→r[j];

           i++;

       }

       while(i<j&&r[i]<=r[j])i++;

       if(i<j){

           r[j]←→r[i];

           j--;

       }

   }

   return i;

}

快速排序算法QuickSort

void QuickSort(intr[],int first,int end)

{

   if(first<end){

       pivot=Patition(r,first,end);

       QuickSort(r,first,pivot-1);

       QuickSort(r,pivot+1,end);

   }

}

8.4选择排序

选择排序是一类借助“选择”进行排序的方法,其主要思想是:每趟排序在当前待排序序列中选出关键码最小的记录,添加到有序序列中。选择排序的特点是记录移动的次数较少。

8.4.1简单选择排序

简单选择排序是选择排序中最简单的排序方法,其基本思想是:第i趟排序在待排序序列r[i]~r[n](1in-1)中选取关键码最小的记录,并和第i个记录交换作为有序序列的第i个记录。

简单选择排序算法SelectSort

void SelectSort(int r[],int n)

{

      for(i=1;i<n;i++)

      {

             index=i;

             for(j=i+1;j<=n;j++)

                    if(r[j]<r[index])index=j;

                    if(index!=i)r[i]←→r[index];

      }

}

8.4.2堆排序

堆排序是简单选择排序的一种改进,改进的着眼点是:如何减少关键码的比较次数。堆排序再选出最小关键码的同时,也找出较小关键码,减少了在后面等选择中的比较次数,从而提高了整个排序的效率。

1、 堆的定义

堆是具有下列性质的完全二叉树:每个结点的值都小于或等于其左右孩子堆点的值(称为小根堆);或者每个结点的值都大于或等于其左右孩子堆点的值(称为大根堆)

从堆的定义可以看出,一个完全二叉树如果是堆,则根节点(称为堆顶)一定是当前堆中所有结点中的最大者或最小者。

筛选法调整堆的算法Sift

void Sift(int r[],int k,int m)

{

      i=k;j=2*1;

      while(j<=m)

      {

             if(j<m&&r[j]<r[j+1])j++;

             if(r[i]>r[j])break;

             else{

                    r[i]←→r[j];

                    i=j;j=2*i;

             }

      }

}

2、 堆排序

堆排序是利用堆的特性进行排序的方法,其基本思想是:首先将待排序的记录序列构造成一个堆,此时,选出了堆中所有记录的最大者即堆顶记录。然后将堆顶记录移走,并将剩余的记录再调整成堆,这样又找出了次大的记录。以此类推,直到堆中只有一个记录为止

堆排序算法HearSort

void HeapSort(int r[],int n)

{

      for(i=n/2;i>=1;i--)

             Sift(r,i,n);

      for(i=1;i<n;i++)

      {

             r[1]←→r[n-i+1];

             Sift(r,i,n-i);

      }

}

8.5归并排序

8.5.1二路归并排序的非递归实现。

具体的排序过程是:将具有n个待排序的记录序列看成是n个长度为1的有序序列,然后进行两辆归并,得到[n/2]个长度为2(最后一个有序序列的长度可能是1)的有序序列,再进行两辆归并,得到[n/4]个长度为4的有序序列(最后一个有序序列的长度可能小于4),……直至得到一个长度为n的有序序列。

一次病归算法 Merge

void Merge(int r[],int r1[],int s,int m,intt)

{

      i=s;j=m+1;k=s;

      while(i<=m&&j<=t)

      {

             if(r[i]<=r[j])r1[k++]=r[i++];

             elser1[k++]=r[j++];

      }

      if(i<=m)while(i<=m0

             r1[k++]=r[i++];

      elsewhile (j<=t)

             r1[k++]=r[j++];

}

一趟归并排序算法MergePass

void MergePass(int r[],int r1[],int n,inth)

{

      i=1;

      while(i<=n-2h+1)

      {

             Merge(r,r1,i,i+h-1,i+2*h-1);

             i+=2*h;

      }

      if(i<n-h+1)Merge(r,r1,i,i+h-1,n);

      elsefor(k=i;k<=n;k++)

             r1[k]=r[k];

}

归并排序非递归算法MergeSort

void MergeSort1(int r[],int r1[],int n)

{

      h=1;

      while(h<n)

      {

             MergeSort(r,r1,n,h);

             h=2*h;

             MergePass(r1,r,n,h);

             h=2*h;

      }

}

8.5.2二路归并排序的递归实现

二路并归排序方法也可以用递归的形式描述,即首先将待排序的记录序列分为两个相等的子序列,并分别将这两个子序列用并归方法进行排序,然后调用一次并归算法Merge,再将这两个有序子序列合并成一个含有全部记录的有序序列。

归并排序的递归算法MergeSort2

void MergeSort2(int r[],int r1[],int s,intt)

{

      if(s==t)r1[s]=r[s];

      else{

             m=(s+t)/2;

             Mergesort2(r,r1,s,m);

             Mergesort2(r,ri,m+1,t);

             Merge(r1,r,s,m,t);

      }

}

0 0