内部排序

#include <stdio.h>
 
void quickSort(int a[], int len);
void shellSort(int a[], int len);
void heapSort(int a[], int len);
//建堆
void createHeap(int a[], int len);
//调整堆
void adjustHeap(int a[], int len);
//求堆高度
int height(int len);
//交换两值
void swap(int *i, int *j);
//打印数组
void print(int a[], int len);
 
int main(){
	int a[10] = { 7, 2, 4, 9, 7, 3, 5, 10, 2, 14 };
	print(a,10);
	//quickSort(a, 10);
	//shellSort(a, 10);
	heapSort(a, 10);
	print(a, 10);
	getchar();
}
 
void print(int a[], int len){
	for (int i = 0; i < len; i++){
		printf("%d   ", a[i]);
	}
	printf("\n");
}

快排

/*快排
先把第一个位置的值保存起来,之后就利用这个空位置,前后交换,真tm经典啊。
*/
void quickSort(int a[], int len){
	int tmp = a[0];
	int start = 0;
	int end = len - 1;
	if (len < 1){
		return;
	}
	while (start < end){
		for (; start < end; end--){
			if (a[end] < tmp){
				swap(a + start, a + end);
				break;
			}
		}
		for (; start < end; start++){
			if (a[start] >tmp){
				swap(a + start, a + end);
				break;
			}
		}
	}
	a[start] = tmp;
	quickSort(a, start);
	quickSort(a + start + 1,len - start - 1);
}
 
void swap(int *i, int *j){
	int tmp = *i;
	*i = *j;
	*j = tmp;
}

堆排

/*堆排
首先你得知道什么是选择排,就是每次选出一个来,至于你怎么选,那就看你了
堆排就是通过堆每次选出堆顶的元素,然后不断的调整堆,关键点也就是建堆和调整堆了
*/
void heapSort(int *a, int len){
	createHeap(a, len);
	while (len > 0){
		swap(a + len - 1, a);
		len--;
		adjustHeap(a,len);
	}
}
 
 
/*如何建堆呢?
以大顶堆为例,在大顶堆的世界里有一条原则,老子总比小子牛逼。
所以你得逐个调整,从最后一个元素开始,如果出现儿子比他爸大的情况,父子换位。
直到第0个元素。但是呢,这循环一次,只能保证一层是满足
“老子总比小子牛逼的”这条哲理的,所以你得这么循环level - 1次
*/
void createHeap(int a[], int len){
	int level = height(len);
	while (level--){
		int i = len - 1;
		while ((i - 1) / 2 >= 0){
			if (a[i] > a[(i - 1) / 2]){
				swap(a + i, a + (i - 1) / 2);
			}
			i--;
		}
	}
}
 
int height(int len){
	int level = 0;
	while (len){
		level++;
		len /= 2;
	}
	return level;
}
 
/*如何调整堆呢?
在调整堆之前我们做的处理是什么,把堆顶的元素和最后一个元素调了个个,
并把len减了1,但是我们不能保证最后一个元素是最大的啊,所以要调整。
但是除了堆顶其余都是满足大顶堆的规则的,我们如果采用建堆时那样未免大材小用了,
比较堆顶孩子的大小关系,将堆顶和两孩子中较大的交换位置,直到叶子,
这样就要保证是大顶堆了 ,弹出堆顶元素,继续堆调整……也很简单吧。
*/
void adjustHeap(int a[], int len){
	int level = height(len);
	int index = 0;
	while (len--){
		int maxIndex = a[2 * index + 1] > a[2 * index + 2] ? 
				(2 * index + 1) : (2 * index + 2);
		if (maxIndex > len){
			break;
		}
		if (a[index] < a[maxIndex]){
			swap(a + index, a + maxIndex);
			index = maxIndex;
		}
	}
}

shell排

/*shell
有问题
*/
void shellSort(int a[], int len){
	int pace[3] = { 1, 3, 5};
	int paceIndex = 2;
	while (paceIndex--){
		//单看这个for循环,有木有冒泡的影子,将pace[paceIndex]换成1,那就变成一模一的冒泡了
		//所以说shell和冒泡是一样一样的,easy!
		for (int i = 0; i < len; i = i + pace[paceIndex]){
			for (int j = 0; j < len - i - pace[paceIndex]; j++){
				if (a[j] > a[j + pace[paceIndex]]){
					swap(a + j, a + j + pace[paceIndex]);
				}
			}
		}
	}
}

内部排序算法的时间复杂度和稳定性

排序算法 平均时间复杂度 最坏时间复杂度 辅助内存 稳定性
冒泡排序 O(n^2) O(n^2) O(1) 稳定
直接插入 O(n^2) O(n^2) O(1) 稳定
选择排序 O(n^2) O(n^2) O(1) 不稳定
shell排序 value value 不稳定
快速排序 O(nlgn) O(n2) O(lgn) 不稳定
堆排序 O(nlgn) O(nlgn) O(1) 不稳定
归并排序 O(nlgn) O(nlgn) O(n) yes
基数排序 O(d(n+rd)) O(d(n+rd)) O(rd) 稳定

参考

[复杂度速查]http://bigocheatsheet.com/