《算法》排序这章的记录,还是看书好啊
从N个输入中找到最大的M个元素所需成本
示例 | 时间 | 空间 |
---|---|---|
排序算法时间 | logN l o g N | N N |
调用初级实现的优先队列 | NM N M | M M |
调用基于堆实现的优先队列 | NlogM N l o g M | M M |
优先队列的各种实现在最坏情况下运行时间的增长数量级
数据结构 | 插入元素 | 删除最大元素 |
---|---|---|
有序数组 | N N | 1 1 |
无序数组 | 1 1 | N N |
堆 | logN l o g N | logN l o g N |
理想情况 | 1 1 | 1 1 |
各种排序算法的性能特点
算法 | 是否稳定 | 是否为原地排序 | 时间复杂度 | 空间复杂度 | 备注 |
---|---|---|---|---|---|
选择排序 | 否 | 是 | N2 N 2 | 1 1 | |
插入排序 | 是 | 是 | 介于 N N 和 N2 N 2 之间 | 1 1 | 取决于输入元素的排列情况 |
希尔排序 | 否 | 是 | NlogN N l o g N ? N6/5 N 6 / 5 ? | 1 1 | |
快速排序 | 否 | 是 | NlogN N l o g N | lgN l g N | 运行效率由概率提供保证 |
三向快速排序 | 否 | 是 | 介于 N N 和 NlogN N l o g N 之间 | lgN l g N | 运行效率由概率保证,同时也取决于输入元素的分布情况 |
归并排序 | 是 | 否 | NlogN N l o g N | N N | |
堆排序 | 否 | 是 | NlogN N l o g N | 1 1 |
一些问题:
- 快速排序为什么快?
快速排序之所以最快是因为它的内循环中的指令很少(而且它还能利用缓存,因为它总是顺序地访问数据),它的运行时间的增长数量级为
cNlgN c N l g N ,而这里的c比其他线性对数级别的排序算法的应用常数都要小。
附:(部分代码)
选择排序
package cn.net.pikachu.sort;
public class Selection {
public static void sort(Comparable[] a){
int N = a.length;
for(int i=0;i<N;i++){
int min = i;
for(int j=i+1;j<N;j++){
if(less(a[j],a[i])){
min = j;
}
}
exch(a,i,min);
}
}
}
插入排序
package cn.net.pikachu.sort;
public class Insertion {
public static void sort(Comparable[] a){
int N = a.length;
for(int i = 1;i<N;i++){
for(int j= i;j>0; && less(a[j],a[j-1];j--){
exch(a,j,j-1);
}
}
}
}
希尔排序
package cn.net.pikachu.sort;
public class Shell{
public static void sort(Comparable[] a){
int N = a.length;
int h = 1;
while(h<N/3){
h = 3*h+1;
}
while(h >=1){
for(int i=h;i<N;i++){
for(int j=i;j>=h && less(a[j],a[j-h]);j-=h){
exch(a,j,j-h);
}
}
h/=3;
}
}
}
归并排序
package cn.net.pikachu.sort;
class Merge{
private static Comparable[] aux;
public static void sort(Comparable[] a){
aux = new Comparable[a.length];
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a, int lo, int hi){
if(hi<=lo){
return ;
}
int mid = lo + (hi-lo)/2;
sort(a,lo,mid);
sort(a,mid+1,hi);
merge(a,lo,mid,hi);
}
}
快速排序
package cn.net.pikachu.sort;
public class Quick{
public static void sort(Comparable[] a){
sort(a,0,a.length-1);
}
private static void sort(Comparable[] a, int lo, int hi){
if(hi<=lo){
return;
}
int j = partition(a,lo,hi);
sort(a,lo,j-1);
sort(a,j+1,hi);
}
private static int partition(Comparable[] a, int lo, int hi){
int i = lo;
int j = hi + 1;
Comparable v = a[lo];
while(true){
while(less(a[++i],v)){
if(i==hi){
break;
}
}
while(less[v,a[--j])){
if(j==lo){
break;
}
}
if(i>=j){
break;
}
exch(a,i,j);
}
exch(a,lo,j);
return j;
}
}
优先队列
package cn.net.pikachu.sort;
public class MaxPQ<Key extends Comparable<Key>> {
private Key[] pq;
private int N = 0;
MaxPQ() {
}
MaxPQ(int maxN) {
pq = (Key[]) new Comparable[maxN + 1];
}
MaxPQ(Key[] a) {
}
void insert(Key v) {
pq[++N]=v;
swim(N);
}
Key max() {
}
Key delMax() {
Key max = pq[1];
exch(1,N--1);
pq[N+1]=null;
sink(1);
return max;
}
boolean isEmpty() {
return N == 0;
}
int size() {
return N;
}
private boolean less(int i, int j){
return pq[i].compareTo(pq[j])<0;
}
private void exch(int i, int j){
Key t = pq[i];
pq[i] = pq[j];
pq[j]=t;
}
private void swim(int k){
while(k>1 && less(k/2,k)){
exch(k/2,k);
k = k/2;
}
}
private void sink(int k){
while(2*k <= N){
int j = 2*k;
if(j<N && less(j,j+1)){
j++;
}
if(!less(k,j)){
break;
}
exch(k,j);
k = j;
}
}
}