在数据结构里面,选择排序又简单的分为简单选择排序及堆排序,都为不稳定排序
一、简单选择排序
在要排序的一组数中,选出最小(或者最大)的一个数与第1个位置的数交换(这里采用最小值);然后在剩下的数当中再找最小(或者最大)的与第2个位置的数交换,依次类推,直到第n-1个元素(倒数第二个数)和第n个元素(最后一个数)比较为止。
简单选择排序的实现
#define MAXSIZE 20 //默认定义数据大小为20
#define T int
typedef T Seqlist[MAXSIZE];
void swap(T *a,T *b)
{
T temp = *a;
*a = *b;
*b = temp;
}
int Select_min_pos(Seqlist &L,int k,int n)//确定最小值的位置确定
{
T min_val = L[k];
int pos = k;
for(int i=k+1;i<n;++i)
{
if(L[i] < min_val)
{
min_val = L[i];
pos = i;
}
}
return pos;
}
void Select_sort(Seqlist &L,int n) //选择排序
{
for(int i = 0;i<n-1;++i)
{
int j = Select_min_pos(L,i,n);
if(j != i)
{
swap(&L[j],&L[i]);
}
}
}
二、堆排序
堆排序是一种树形选择排序,是对直接选择排序的有效改进。
堆的定义如下:具有n个元素的序列(k1,k2,…,kn),当且仅当满足
时称之为堆。由堆的定义可以看出,堆顶元素(即第一个元素)必为最小项(小顶堆)。
若以一维数组存储一个堆,则堆对应一棵完全二叉树,且所有非叶结点的值均不大于(或不小于)其子女的值,根结点(堆顶元素)的值是最小(或最大)的。如:
(a)大顶堆序列:(96, 83,27,38,11,09)
(b) 小顶堆序列:(12,36,24,85,47,30,53,91)
初始时把要排序的n个数的序列看作是一棵顺序存储的二叉树(一维数组存储二叉树),调整它们的存储序,使之成为一个堆,将堆顶元素输出,得到n 个元素中最小(或最大)的元素,这时堆的根节点的数最小(或者最大)。然后对前面(n-1)个元素重新调整使之成为堆,输出堆顶元素,得到n 个元素中次小(或次大)的元素。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。称这个过程为堆排序。
堆排序的实现
#define MAXSIZE 20 //默认定义数据大小为20
#define T int
typedef T Seqlist[MAXSIZE];
void swap(T *a,T *b)
{
T temp = *a;
*a = *b;
*b = temp;
}
void siftdown(T heap[],int n,int p)//向下调整
{
int i = p;//小堆结构里的父节点
int j = 2*i + 1;//小堆的左子树
while(j<n)
{
if(j<n-1 &&heap[j]>heap[j+1])
j++; //保证j指向子树里面的较小值
if(heap[i]<=heap[j])
break;
else
{
swap(&heap[i],&heap[j]);//如果小堆结构里面父节点大于子树,交换它俩的值
i = j;
j = 2*i+1;
}
}
}
T remove_min_key(T heap[],int n)
{
T key = heap[0];
heap[0] = heap[n];
siftdown(heap,n,0);//重新向下调整
return key;
}
void Heap_sort(Seqlist &L,int n)
{
T *heap = (T*)malloc(sizeof(T) * n);
assert(heap != NULL);
int i;
for( i = 0;i<n;++i)
{
heap[i] = L[i];
}
int curpos = n/2 -1;//最底层小堆结构
while(curpos >= 0)
{
siftdown(heap,n,curpos);
curpos--;
}
for(i = 0;i<n;++i)
{
L[i] = remove_min_key(heap,n-i-1); //每次去掉小堆结构的最顶端,即最小值
}
free(heap);
heap=NULL;
}
堆排序测试文件
void main() {
Seqlist L = {16,33,9,8,25,21,3,49,5};
int n = 9;
Heap_sort(L,n);
for(int i = 0;i < n;++i)
{
cout<<L[i]<<" ";
}
}
建堆时的比较次数不超过4n 次,因此堆排序最坏情况下,时间复杂度也为:O(nlogn )。堆排序是一种不稳定排序