选择排序

选择排序的基本思想是:每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子表的最后,直到全部记录排序完毕。

两种选择排序方法:(1)简单选择排序(或称直接选择排序)(2)堆排序

一、直接选择排序

基本思想:第i趟排序开始时,当前有序区和无序区分别为R[0..i-1]和R[i..n-1](0≤i<n-1),该趟排序则是从当前无序区中选出关键字最小的记录R[k]将它与无序区的第1个记录R[i]交换,使R[0..i]和R[i+1..n-1]分别变为新的有序区和新的无序区。

void SelectSort(RecType R[],int n)
{  int i,j,k;  RecType temp;
   for (i=0;i   {  k=i;
for (j=i+1;j    if (R[j].key      k=j;           //k记下的最小关键字所在的位置
if (k!=i)           //交换R[i]和R[k] 
{  temp=R[i];  R[i]=R[k];  R[k]=temp;  }
    }

 }

例1 设待排序的表有10个记录,其关键字分别为{6,8,7,9,0,1,3,2,4,5}。说明采用直接选择排序方法进行排序的过程。

选择排序_第1张图片 

对 n 个记录进行简单选择排序,所需进行的 关键字间的比较次数 总计为:选择排序_第2张图片

二、堆排序

堆排序是一树形选择排序,它的特点是,在排序过程中,将R[1..n]看成是一棵完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(或最小)的记录

堆的定义是:n个关键字序列K1,K2,…,Kn称为堆,当且仅当该序列满足如下性质(简称为堆性质):

(1)Ki≤K2i 且 Ki≤K2i+1   或

(2)Ki≥K2i 且 Ki≥K2i+1(1≤i≤n/2)

 满足第(1)种情况的堆称为小根堆,满足第(2)种情况的堆称为大根堆。下面讨论的堆是大根堆。

例如:{12, 36, 27, 65, 40, 34, 98, 81, 73, 55, 49}是小根堆


调整堆:完全二叉树的左右子树都满足堆的条件、仅根节点不满足堆的条件

void sift(RecType R[],int low,int high) //调整堆的算法

{  int i=low,j=2*i;    //R[j]是R[i]的左孩子
   RecType temp=R[i];
   while (j<=high) 
   {  if (j        if   (temp.key        {  R[i]=R[j]; //将R[j]调整到双亲结点位置上
     i=j;       //修改i和j值,以便继续向下筛选
         j=2*i;
  }

  else break;   
   }
   R[i]=temp;

}

堆排序:将根节点与最后的一个叶子节点顺序交换,交换后输出根节点,叶子节点作为根调整进行下一轮排序

实现堆排序的算法如下:

void HeapSort(RecType R[],int n)
{  int i; RecType temp;
   for (i=n/2;i>=1;i--) //循环建立初始堆
      sift(R,i,n); 
   for (i=n;i>=2;i--)  //进行n-1次循环,完成推排序
   {  temp=R[1];       //将第一个元素同当前区间内R[1]对换
      R[1]=R[i];R[i]=temp;
      sift(R,1,i-1);   //筛选R[1]结点,得到i-1个结点的堆
   }

}


例2 设待排序的表有10个记录,其关键字分别为{6,8,7,9,0,1,3,2,4,5}。说明采用堆排序方法进行排序的过程。

选择排序_第3张图片

排序:

选择排序_第4张图片

选择排序_第5张图片

1. 对深度为 k 的堆,“筛选”所需进行的关键字,比较的次数至多为2(k-1)

2. 对 n 个关键字,建成深度为h(=log2n+1)的堆,所需进行的关键字比较的次数不超过4n

3. 调整“堆顶” n-1 次,总共进行的关键字比较的次数不超过

 2 (log2(n-1)+ log2(n-2)+ …+log22) < 2n(log2n) 

因此,堆排序的时间复杂度为O(nlogn)。

你可能感兴趣的:(数据结构学习,第十章:内排序)