1. 简单选择排序
a. 基本思想
其实思路很简单,就是第i趟排序中从L[i…….n]中,选出关键字最小的元素与L[i]交换。每趟确定一个元素的最终位置。
L[1…..i-1] | L[i] | L[i+1……n] |
---|
b. 代码
void SelectSort(ElemType A[], int n){
//对表A作简单选择排序,A[]从0开始存放元素
for(i=0;i<n-1;i++){ //一共进行n-1趟
min = i; //记录最小元素位置
for(j=i+1;j<n;j++)
if(A[j]<A[min]) min = j;
if(min!=i) swap(A[i],A[min]); //交换
}
}
c. 性能描述
这个很简单,直接说明即可。空间复杂度O(1), 时间复杂度O(n^2). 不稳定的排序方法。[#2, 2, 1]->[1, #2, 2 ]
2. 堆排序(比较重要的一种排序)
a. 基本思想
堆排是一种树形选择排序方法,特点:在排序过程中,将L[1…….n]看成一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子节点之间的内在关系,在当前无序区中选择关键字最大(或最小)的元素。
堆的定义:小根堆 — L[i]<=L[2i]且L[i]<=L[2i+1]。通俗一点就是父节点关键字大于左右孩子节点。
大根堆 — L[i]>=L[2i] 且L[i]>=L[2i+1]。父节点关键字小于左右孩子节点的关键字。
b. 堆排实现方法
1). 最关键的是构造初始堆。示意图
2). 代码(这是建大顶堆的代码)
void BuildMaxHeap(ElemType A[], int len){
for(int i=len/2;i>0;i--) //从i=n/2到1,反复调整
AdjustDown(A, i , len);
}
void AdjustDown(ElemType A[],int k,int len){
//向下调整堆的算法,将元素k向下进行调整
A[0] = A[k]; //暂存A[k]
for(i=2*k;i<=len;i*=2){ //沿key较大的子节点向下筛选
if(i<len&&A[i]<A[i+1])
i++; //取key较大的子节点的下标
if(A[0]>=A[i]) break; //筛选结束
else {
A[k]=A[i]; //将A[i]调整到双亲节点上
k=i; //修改k值,以便继续向下筛选
}
}//for
A[k] = A[0]; //被筛选值放入最终位置。
}
void AdjustUp(ElemType A[],int k){
//向上调整堆的算法。参数k是堆的元素个数(这个出题,考察较多),也是向上调整的结点
A[0] = A[k];
int i = k/2;
while(i>0&&A[i]<A[0]){ //循环跳出
A[k] = A[i]; //双亲节点下调
k=i;
i=k/2; //继续向上比较
}//while
A[k] = A[0]; //复制到最终代码
}
3). 输出代码
void HeadSort(ElemType A[],int len){
BuildMaxHeap(A,len); //初始建大根堆
for(i=len;i>1;i--){ //n-1趟的交换和建堆过程
Swap(A[i],A[1]); //输出堆顶元素(和堆底元素交换)
AdjustDown(A,1,i-1); //整理,把剩下的i-1个元素整理成堆
}
}
c. 性能分析
空间效率:O(1)
事件效率:建堆时间为O(n),时间复杂度O(h*logn)
稳定性:不稳定的排序方法