八大排序总结

1. 插入排序—直接插入排序(Straight Insertion Sort)

顾名思义,直接插入排序就是将一个记录插入一个已经排好序的数组中,使原本排好序的数组添加了一个记录并且继续保持排好序。如果在比较时两个记录相等,则把插入的记录放到原先记录的后面,所以插入排序是稳定的。

时间复杂度:O(n^2)

void InsertSort(int a[], int n)  
{  
    for(int i= 1; i<n; i++){
        int j= i;//插入位置 
        int x = a[i];//插入有序数组的记录 
        while(x < a[j - 1]){//比较,查找在有序数组的插入位置  
            a[j] = a[j - 1];//数组后边的记录后移 
            j--;//新记录前移
        }  
        a[j] = x;//找到正确的位置,插入
    }  
}  

2. 快速排序(Quick Sort)

快排的基本思路不难理解,主要是优化方面比较难。

基本思路:在数组选出一个基准点 key ,把它放在一个位置使得在它后边的数都比它大(或者相等),在它前边的数都比它小(或者相等)。在这里我们选取数组的第一个记录作为 key ,然后把它拿出来,这样就空下一个位了,我们设置两个”寻找者“---- first 和 last,初始化为数组头和数组尾,因为第一个空位在数组前,那么我们就从数组尾找,last 就从尾部开始找,当找到了一个比 key 小的数(或者等于),那么就可以把它移到原先的空位,同时也产生了一个新的空位,同样地,我们就让 first 寻找合适的数来填上,当 last == first 时,那个位置就是 key 的咯。这样第一轮就结束了,接着,把数组分成两份再次用同样的方法进行寻找(其实这种就是分治的思路),直到数组被分得只有一个。

复杂度分析:当每次找得的 key 都是数组的中间位置,那么复杂度就最好的咯,也就是 O(nlogn),如果每次找得的 key 都是数组的第一个位置(也就是数组已经是排好序的),那么复杂度就是最差的,O(n²)。因此,key的选取关系到复杂度,很多优化都是围绕 key 的选取,有的选取数组第一,中间,末尾三个位置的中间值(三平均分区法),也有的让 key 随机选取(随机化快排)等等。快排过程中相同值的记录有可能调换位置,所以快排是不稳定的。


void Qsort(int a[], int low, int high){
	if(low < high){
		int first = low;
		int last = high;
		int key = a[first];
		while(first < last){
			while(first < last && a[last] >= key){
				last--;
			}
			a[first] = a[last];
			while(first < last && a[first] <= key){
				first++;
			}
			a[last] = a[first];
		}
		a[first] = key;
		Qsort(a, low, first - 1);
		Qsort(a, first + 1, high);
	}
} 


3. 归并排序(Quick Sort)

归并排序同样也是利用分治的思想,相比快排,其复杂度是稳定的。

基本思路:将数组分成两个排好序的数组,分别储存在两个其他数组中,然后把它们归并到原来的数组中(因为两个数组都是排好序的,所以很容易实现)。那么如何将原来的数组得到两个排好序的数组呢?就是使用分治,把数组分成两半,每一部分都是利用相似的办法处理,最终 dfs 回来的就是一个排好序的数组。在归并过程中可以使相同值的记录保持原来的排序,所以该算法是稳定的。

复杂度分析:各种请况的复杂度都是一样的,即是O(nlogn)



int L[N], R[N];
void MergeSort(int a[], int p, int q){
	if(p < q){
		int m = (q - p) / 2 + p;
		MergeSort(a, p, m);
		MergeSort(a, m + 1, q);
		int l = 0, r = 0;
		for(int i = p; i <= m; i++){
			L[l++] = a[i];
		}
		L[l] = INT_MAX;
		for(int i = m + 1; i <= q; i++){
			R[r++] = a[i];
		}
		R[r] = INT_MAX;
		l = 0; r = 0;
		for(int i = p; i <= q; i++){
			if(L[l] <= R[r]){
				a[i] = L[l++];
			}
			else{
				a[i] = R[r++];
			}
		}
	}
}


4. 选择排序(Selection Sort)

选择排序比较简单,比较好理解。

基本思路:每次找出最小值,然后进行交换。但交换过程有可能把相同值的记录的相对位置交换,导致算法不稳定(比如:5,4, 5, 2, 3 这一组,第一轮交换把第一个 5 和 2 交换,导致两个 5 的相对位置变了)

复杂度分析:算是一种朴素的算法,复杂度为 O(n²)


void SelectionSort(int a[], int p, int q){
	for(int i = p; i <= q; i++){
		int min = i;
		for(int j = i + 1; j <= q; j++){
			if(a[min] > a[j]){
				min = j;
			}
		}
		swap(a[i], a[min]);
	}
}


其他的以后再补充。。。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值