数据结构—排序II
来源:互联网 发布:无网络小游戏 编辑:程序博客网 时间:2024/05/22 02:10
一. 选择排序
【基本思想】每一趟(比如第i趟)在后面 n-i+1(包括第i个元素)个待排元素中选取关键字最小的元素,作为有序子序列(前1…i-1个有序元素)的第i个元素,直到第n-1趟做完,待排元素只剩下一个,就不用再选了(也就是说只选择了第1,2….n-1号元素)
A. 简单选择排序
【算法思想】 假设排序表为L[1….n],第i趟排序即从L[ i… n ]中选择关键字最小的元素和L(i)交换,每一趟排序可以确定一个元素的最终位置,这样经过n-1趟排序就可以使得整个排序表有序。
【伪代码】
Void SelectSort(ElemType A[],intn)
{
//[0]号单元也存放元素
For(i=0;i<n-1;i++) //一共进行n-1趟
{
Min=I; //记录最小元素位置
For(j=i+1;j<n;j++) //在A[i…..n-1]中选择最小元素
If(A[j]<A[min]
Mi=j; //更新最小元素位置
If(min!=i)SWAP(A[i],A[min]); //与第i个位置交换
}
}
【性能分析】
空间效率:仅使用了常数个辅助单元(记录最小位置),故空间复杂度为O(1)
时间效率:从简单排序过程可见,元素移动的次数很少,不会超过3(n-1)次,最好的情况是移动0次,此时对应表有序;但元素间比较次数与序列初始状态无关,始终是n(n-1)/2次( ),(因为是比较之后才判定是否更新并移动)所以时间复杂度始终是O(n^2).
稳定性:在第i趟找到最小元素后,和第i个元素交换,可能会导致第i个元素与其含有相同关键字元素的相对位置改变。 例如,表L={2,2,1}第一趟排序后,L={1,2,2},最终排序序列也是L={1,2,2},可见相对顺序可能发生改变(因为有了交换)
B. 堆排序
【特点】 是一种树形选择排序方法,在排序过程中,将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) 大根堆 (1<=i< ⌊n/2⌋)--因为是二叉树嘛
堆排序的关键是构造初始堆,对初始序列建堆,就是一个反复筛选的过程。N个结点的完全二叉树,最后一个结点是第⌊n/2⌋个结点的孩子(浅显地理解是因为二叉树中双亲结点有两个孩子结点的性质,向下取整的是保证了n+1号节点也取到和n号节点相同的双亲结点)。
【建堆时间复杂度】向下调整的时间和树高有关,为O( )。建堆过程中每次向下调整,大部分结点的高度都较小。可以证明:
在元素个数为n的序列上建堆,其时间复杂度为O(n)。
【堆排序】
思路:首先将存放在L[1…n]中的n个元素建成初始堆,由于堆本身特点(以大顶堆为例),堆顶元素就是最大值。输出堆顶元素后,通常将堆底元素送入堆顶,此时根结点已不满足大顶堆的性质,堆被破坏,将堆顶元素向下调整使其继续保持大顶堆的性质,再输出堆顶元素,如此重复,直到堆中仅剩一个元素为止。
代码:
VoidHeapSort(ElemType A[],int len)
{
BuildMaxHeap(A,len); //建初始堆
For(i=len;i>1;i--) //n-1趟交换和调整过程,直到剩下最后一个元素
{
//输出堆顶元素
Swap(A[i],A[len]); //交换
AdjustDown(A,1,i-1); //调整,把剩余n-1个元素调整成堆
}
}
【性能分析】
空间效率:仅使用了常数个辅助单元(A[0],这种排序称之就地排序),所以空间复杂度为O(1)
时间效率:建堆时间为O(n),之后又n-1次向下调整操作,每次调整的时间复杂度为O(h)即O( 。故在最好,最坏,平均情况下,堆排序时间复杂度始终为O(n 。(因为它和输入序列无关,不管有序无序,相对比较次数始终是不变的)
稳定性:在进行调整时,有可能把后面相同的关键字调整到前面,例如表L={2,2,1},构造初始小顶堆时,会把1交换到堆顶,此时L={1,2,2},结果也是L={1,2,2},可见相同关键字的相对位置发生了变化,故堆排序是一种不稳定排序方法。
【补充:堆插入】
步骤:
1. 先将新结点放在堆末端
2. 再对这个新结点执行一次向上调整操作即可 (很明显,由于是叶子结点可能向下调整呀)
代码:
VoidAdjustUP(ElemType A[],int k)
{
//参数k为向上调整的结点,也为堆的元素个数,
A[0]=A[k];
Int i=k/2; //大根堆:若子结点值大于双亲结点,则将双亲结点下调,并继续向上比较。
While(i>0&&A[i]<A[0]) //直到根结点为止或双亲结点大于子结点时
{
A[k]=A[j]; //交换
K=I; //k为当前子结点
I=k/2; //i为当前双亲结点
}
A[k]=A[0]; //复制到最终位置
}
- 数据结构—排序II
- 数据结构—图II
- 数据结构—图II
- 数据结构 — 查找II
- 数据结构 — 查找II
- 数据结构——排序
- 数据结构——排序
- 《数据结构》——排序
- 数据结构——排序
- 数据结构—排序算法
- 数据结构—希尔排序
- 数据结构—排序总结
- 数据结构 — 归并排序
- 数据结构 — 堆排序
- 数据结构—排序
- 数据结构—排序I
- 数据结构—排序III
- 数据结构—排序IV
- js工具集
- python笔记
- 数据结构 — 查找IV
- 算法课第3周第2题——207. Course Schedule
- 数据结构—排序I
- 数据结构—排序II
- 数据结构—排序III
- PPM是什么单位
- 数据结构—排序IV
- JavaI/O 学习笔记之一:字符流操作
- [学习日志][2-2-1][裸机开发快速体验]
- Multi-thread: What is the difference between OpenMP and MPI
- Leetcode 2 Add Two Numbers
- java I/O之装饰设计模式