一 选择排序
(1)思想
假设有十张扑克牌放在桌上,我们需要按从小到大的顺序拿到手上,每次只能选择一张牌拿到手上,那么每一次我们都必须从桌上的扑克牌中选择最小的牌拿起来,一次循环十次,这样就将扑克牌按从小到的顺序拿到手上了。这就是选择排序。
(2)实现
//选择排序
//输入:待排序数组(A)和数组个数(n)
//输出:按从小到大排序的数组(A)
void Select_sort(SortArray *A,int n)
{
int i,j,min;
int temp;
for (i = 0 ; i < n -1 ; i++)
{
min = i;
for (j = i+1 ; j < n ; j++)
{
if ((*A)[min] > (*A)[j])
{
min = j;
}
}
if (i != min)
{
temp = (*A)[i];
(*A)[i] = (*A)[min];
(*A)[min] = temp;
}
}
}
选择排序是一种简单直观的排序算法,但它并不稳定。其不稳定性体现在:如果一个元素比当前元素小,而该小的元素又出现在一个和当前元素相等的元素后面,那么交换后的稳定性就被破坏了(百度百科解释),照我的理解应该是,如果按序列(3,5,3,2,1)来说,在当前序列中前一个3的优先级大于后面的3,但是第一次排序就将第一个3换到了后面,因此该算法不稳定。
选择排序优于冒泡排序,其比较次数减少了,但是其算法复杂度依然是O(N2).
二 堆排序算法
(1) 思想
在选择排序中,我们每次从待排序数组中选择最小的数是根据遍历数组比较得来的,这种方法的效率低。
在堆排序中,利用最小/最大堆来获取待排序数组的最小/最大值。
(2) 实现
在堆排序中,最重要的是构建最大堆。
//构建 最大堆
void Heap_adjust(SortArray *A , int s , int n)
{
int temp , i ;
temp = (*A)[s];
for (i = 2*s+1 ; i <= n ; i = 2*i +1)
{
if (i < n-1 && (*A)[i] < (*A)[i+1])
{
++i;
}
if (temp > (*A)[i])
{
break;
}
(*A)[s] = (*A)[i];
s=i;
}
(*A)[s] = temp;
}
构建最大堆的时间复杂度0(n)
堆排序算法
void Heap_sort(SortArray *A,int n)
{
int i;
for (i = n/2-1 ; i >=0; i--)
{
Heap_adjust(A,i,n-1);
}
for (i = 0 ; i <n ; i ++)
{
cout<<(*A)[i]<<endl;
}
for ( i = n -1 ; i >=0 ; i--)
{
int temp = (*A)[0];
(*A)[0] = (*A)[i];
(*A)[i] = temp;
Heap_adjust(A , 0 , i-1);
}
}
在堆排序中,需要反复重建最大堆,其时间复杂度为O(nlogn)
所以,总时间复杂度为O(nlogn),其优于冒泡排序和选择排序等。
附:主程序代码
#include <stdio.h>
#include "stdafx.h"
#include <iostream>
using namespace std;
#define MAX 100
typedef int SortArray[MAX];
int _tmain(int argc, _TCHAR* argv[])
{
int n ;
SortArray A;
cout<<"/**选择排序和堆排序**/\n"
<<"请输入数组个数"<<endl;
cin>>n;
cout<<"请输入待排序数组"<<endl;
for (int i = 0 ; i < n ; i++)
{
cin>>A[i];
}
cout<<"正在排序请稍后....."<<endl;
//Bubble_sort(&A,n);
//Select_sort(&A,n);
//Insert_sort(&A,n);
//Shell_sort(&A,n);
Heap_sort(&A,n);
cout<<"排序结果如下....."<<endl;
for (int i = 0 ; i < n ; i++)
{
cout<<A[i]<<endl;
}
system("pause");
return 0;
}