选择排序:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,放在已排好序的数列的最后,直到全部待排序的数据元素排完。它是一种不稳定的排序方法。选择排序前半部分逐渐有序,每趟是从待排序的数据元素位置开始扫描。
典型的选择排序算法:
(1) 直接选择排序
(2) 堆排序
直接选择排序代码:
//简单选择排序
bool SelectSort1(int A[],int n)
{
if (A==NULL&n<0)
{
printf("Parameter for function SelectSort error!\n");
return false;
}
for (int i=0;i<n;i++)
{
for (int j=i+1;j<n;j++)
{
if (A[j]>A[i])
{
int temp = A[j];
A[j] = A[i];
A[i] = temp;
}
}
}
return true;
}
上述代码中,每次比较发现A[j]>A[i],就交换。可优化为如下的形式:
bool SelectSort2(int A[],int n)
{
if (A==NULL&n<0)
{
printf("Parameter for function SelectSort error!\n");
return false;
}
for (int i=0;i<n;i++)
{
int k = i;
for (int j=i+1;j<n;j++)
{
if (A[j]>A[k]) //并不需要每次都交换
{
k = j;
}
}
if (k!=i)
{
int temp = A[k];
A[k] = A[i];
A[i] = temp;
}
}
return true;
}
直接选择排序的时间复杂度为O(n^2),同样是不稳定的。
堆排序:
当然,这是小顶堆,大顶堆则相反。
如果把堆序列所对应的数组,看作一个完全二叉树的顺序存储,那么,我们可以发现这颗二叉树满足如下的性质:任意分值支节点的值小于等于它左右孩子节点的值,即每一个分支节点是以它为树根的树中的最小者。
小图为一个小顶堆和大顶堆
我们可以看到,对于一个数组,如果我们用该数组建一个小顶堆所对应的完全二叉树,则树的根节点即为最小值。然后我们删除根节点,重新建堆,又可找到次小值,依次类推,即可完成排序。
//A[k]数组元素从小标1开始,并不从0开始
//堆调整
//A[]的大小为size+1,size为实际待排序的数的个数
void HeapAdjust(int A[],int k,int size)
{
int lchild = 2*k;
int rchild = 2*k+1;
int index = k;
if(lchild<=size&&A[lchild]<A[index])
{
index = lchild;
}
if(rchild<=size&&A[rchild]<A[index])
{
index = rchild;
}
if(index!=k) //index=lchild或者index=rchild
{
int A[0] = A[index];
A[index] = A[k];
A[k] = A[0];
HeapAdjust(A,index,size);//调整以index为根的树使其为堆
}
}
void CreateHeap(int A[],int size)
{
for(int i=size/2;i>=1;i--)
{
HeapAdjust(A,i,size);
}
}
bool HeapSort(int A[],int size)
{
if(A==NULL||size<=0)
{
printf("Parameter for function HeapSort error!\n");
return false;
}
CreateHeap(A,size); //创建完成后,A[1]为最小值了
for(int i=size;i>1;i--)
{
A[0] = A[1];
A[1] = A[i];
A[i] = A[0];
HeapAdjust(A,1,i-1);
}
return true;
}
上面代码中堆的调整使用的是递归实现的,现在使用非递归实现:
//HeapAdjust的非递归实现
void HeapAdjust(int A[],int k,int size)
{
int j = 2*k;
int minIndex = k; //minIndex以k为根的树的最小值的下标
bool finish = false;
int A[0] = A[k];
while(j<=size&&!finish)
{
if(j<size&&A[j+1]<A[j]) //右子树比左子树小
{
j++;
}
if(A[minIndex]>A[j]) //此时j为左右子树种的较小者
{
//根节点比孩子节点大,需调整
A[minIndex] = A[j];
//调整以左右孩子节点为根的树为堆
minIndex = j;
j = 2*j;
}
else //不需要调整
{
finish = true;
}
}
A[minIndex] = A[k];
}
参考:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html