排序篇-内部排序-选择排序

151 阅读1分钟

简单选择排序

  • 时间复杂度 O(n^2)
  • 空间复杂度 O(1)
  • 稳定性 不稳定
  • 基本思想 每趟循环从待排序元素中选出一个最小(最大)的元素排到i位置。直到n-1趟排序做完,数组有序。

代码实现

void selectSort(int *a, int n){
	int min;
    for(int i = 0; i < n - 1; i ++){
    	min = i;
        for(int j = i + 1; j < n; j ++){
        	if(a[j] < min){
            	swap(a, j, min);
                min = j;
            }
        }
    }
}

堆排序

堆的定义:n个关键字序列称为堆,当且仅当该序列满足:

  • L(i) >= L(2i) 且L(i) >= L(2i+1) -- 大根堆
  • L(i) <= L(2i) 且L(i) <= L(2i+1) -- 小根堆

快速排序优于堆排序的原因:

  • 快速排序对CPU缓存更友好
  • 快速排序的比较次数少于堆排序

大根堆代码实现

//调整以k为根的树为大根堆
void heapAjust(int *a ,int n, int k){
	int root = a[k];
    int i = 2 * k + 1;
    while(i < n){
    	if((i + 1) < n && a[i] < a[i + 1]){
        	i ++;
        }
        if(root < a[i]){
        	a[k] = a[i];
            k = i;
            i = 2 * i + 1; //更新子元素
        }else{ //已k为根的树满足大根堆要求
        	break;
        }
   	}
  	a[k] = root;
}

//初始化大根堆
void buildMaxHeap(int *a, int n){
	for(int i = n / 2; i >= 0; i --){
    	heapAjust(a, n, k);
    }
}

//删除堆顶元素
void remove(int *a, int n){
	a[0] = a[n - 1];
    heapAdjust(a, n, 0);
}

void heapSort(int *a, int n){
	buildMaxHeap(a, n);
    for(int i = n - 1; i > 0; i --){
    	swap(a, 0, i);
        heapAjust(a, i, 0);
    }
}

堆的典型应用

堆的典型应用可以看看极客上王争老师的《数据结构与算法》

  • 求topK
  • 求中位数
  • 合并有序小文件
  • 高性能定时器

求topK

基本思想:初始化含K的元素的小顶堆,遍历比较剩余数据,如果元素大于堆顶元素,则用该元素替换堆顶元素,并做一次堆化操作,否则继续比较下一个元素。