选择排序的基本思想:每一趟(例如第i趟)在后面n-i+1(i=1,2,…n-1)个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到第n-1趟做完,待排序元素只剩下了1个,就不用再选了。
1.简单选择排序
简单排序算法思想:假设排序表为L[1…n],第i趟排序即从L[i…n]中选择关键字最小的元素与L(i)交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟排序就可以使得整个排序表有序。代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
void Swap(int *a, int *b);
void SelectSort(int a[], int n);
int main(){
int n;
printf("请输入元素的个数:\n");
scanf("%d",&n);
int a[n];
printf("请输入数组中的元素:\n");
for(int i=0; i<n; i++){
scanf("%d", &a[i]);
}
SelectSort(a, n);
printf("请输出排序好的数组:\n");
printf("请输出排序好的数组:\n");
for(int i=0; i<n; i++){
printf("%d ",a[i]);
}
return 0;
}
void Swap(int *a, int *b){
int temp;
temp = *b;
*b = *a;
*a = temp;
}
SelectSort(int a[], int n){
for(int i=0; i<n-1; i++){ //n-1趟
int min = i; //记录最小元素的位置
for(int j= i+1; j<n; j++) //在a[i...n]中选择最小的元素
{
if (a[j]< a[min]) min = j; //更新最小元素的位置
if(min != i) Swap( &a[i],&a[min]);
}
}
}
编译运行结果如下:
2.堆排序
堆排序思路:首先将存放在L[1…n]中的n个元素建成初始堆,由于堆本身的特点,堆顶元素就是最大值,输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大根堆的性质,堆被破坏,将堆顶元素向下调整使其继续保持大根堆的性质,再输出堆顶元素,如此反复,直到堆中仅剩下一个元素为止。
堆排序是一种树形选择排序方法,特点:在排序过程中,将L[1…n]看成是一棵完全二叉树的顺序结构,利用完全二叉树中双亲结点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。
堆的定义如下:n个关键字序列L[1…n]称为堆,当且仅当该序列满足:
1.L(i)>=L(2i) 且 L(i)>=L(2i+1) 【大根堆】 2.L(i)<=L(2i) 且 L(i)<=L(2i+1) 【小根堆】
堆排序的关键是构造初始堆,对初始序列建堆,就是一个反复筛选的过程。n个结点的完全二叉树,最后一个结点是第[n/2]个结点的孩子。对第[n/2]个结点为根的子树筛选(对于大根堆:若根结点的关键字小于左右子女中关键字较大者,则交换),使该子树成为堆。之后向前依次对各节点([n/2]-1 ~1)为根的子树进行筛选,看该结点值是否大于其左右子树结点的值,若不是,将左右子结点中较大值与之交换,交换后可能会破坏下一级的堆,于是继续采用上述方法构造下一级的堆,直到以该结点为根的子树构造成堆为止。反复利用上述调整堆的方法建堆,直到根结点。
代码如下:
#include<cstdio>
#include<iostream>
using namespace std;
void HeapSort(int a[], int len);
void BuildMaxHeap(int a[], int len );
void AdjustDown(int a[],int k, int len );
int main(){
int n;
int maxn = 110;
printf("请输入元素的个数:\n");
scanf("%d",&n);
int a[maxn];
printf("请输入数组中的元素:\n");
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
}
HeapSort(a, n);
printf("请输出排序好的数组:\n");
for(int i=1; i<=n; i++){
printf("%d ",a[i]);
}
return 0;
}
void BuildMaxHeap(int a[], int len){
for(int i = len/2;i>0; i--){
AdjustDown(a, i, len);
}
}
void AdjustDown(int a[], int k, int len){
a[0] = a[k]; //a[0]为哨兵
for(int i= 2*k; i<=len; i=i*2){
if(a[i]<a[i+1] &&i<len){
i++;
}
if(a[i] <a[0]) break;
else{
a[k] = a[i];
k = i; //修改K值,继续向下调整
}
}
a[k] = a[0]; //被筛选节点最终位置
}
void HeapSort(int a[], int len){
BuildMaxHeap(a, len); //建造初始堆
for(int i = len; i>1; i--){
swap(a[i], a[1]); //和堆底元素交换
AdjustDown(a, 1, i-1);
}
}
swap()函数链接:swap详解