排序

排序

输⼊: 待排序的数组a[], 元素个数n
输出: 已排序的数组a[]

1. 插入排序

n-1趟排序
0<i<n
第i趟排序处理a[i], 前i个元素有序, 将a[i]插⼊合适的位置

void insertsort(int n) {
	int i, j;
	int t;
	for (i = 1; i < n; ++i) {
		t = a[i];
		for (j = i; j > 0 && a[j - 1] > t; --j) //查找插入位置并移动元素
			a[j] = a[j - 1];
		a[j] = t;                               //插入
	}
}

1.5. *折半插入排序

todo

2. 冒泡排序

n-1次处理
0<i<n
每次处理使最⼤元素沉底

void bubblesort(int n) {
	int i, j;
	for (i = 1; i < n; ++i)
		for (j = 0; j < n - i; ++j)
			if (a[j] > a[j + 1]){
				int t = a[j];
				a[j] = a[j + 1];
				a[j + 1] = t;
			}
}

3. 选择排序

n-1次处理
0<i<n
每次处理使最⼤元素沉底

void choosesort(int n) {
	int i, j;
	for (i = 1; i < n; ++i) {
		int max = INT32_MIN;
		int maxj = 0;
		for (j = 0; j <= n - i; ++j)
			if (a[j] > max) {
				maxj = j;
				max = a[j];
			}
		a[maxj] = a[n - i];
		a[n - i] = max;
	}
}

4. 希尔排序

步⻓为k的插⼊排序称为k-排序
k-排序考察a[k]~a[n-1], 使k个子序列有序
k值的序列称为增量序列,增量序列的选择影响希尔排序的效率,⼀个较简单的增量序列如下所示,但效率不⾼
希尔排序通过⼀系列的k-排序最终使序列有序

void shellsort(int n) {
	int i, j, k;
	int t;
	for(k = n / 2; k > 0; k /= 2)
		for (i = k; i < n; ++i) {
			t = a[i];
			for (j = i; j >= k && a[j - k] > t; j -= k) 
				a[j] = a[j - k];
			a[j] = t;
		}
}

5. 堆排序

将所有元素加⼊堆,再⼀个⼀个弹出

//堆的数据结构及操作略
void heapsort(int n) {
	int i;
	for (i = 0; i < n; ++i)
		insert(a[i]);
	for (i = 0; i < n; ++i) {
		a[i] = heapmin();
		ddelete();
	}
}

6. 归并排序

void gbsort(int left, int right) {
	if (left >= right) return;
	int mid = (left + right) / 2;
	gbsort(left, mid);
	gbsort(mid + 1, right);
	int i, j, k, l;
	for (i = left, j = mid + 1, k = 0; i <= mid && j <= right; ) { //合并
		if (a[i] <= a[j])
			b[k++] = a[i++];
		else
			b[k++] = a[j++];
	}
	if (i > mid)
		for (; j <= right; ++j)
			b[k++] = a[j];
	else
		for (; i <= mid; ++i)
			b[k++] = a[i];
	for (i = left, l = 0; l < k; ++i, ++l) {                       //复制数组
		a[i] = b[l];
	}
}

7. 快速排序

快速排序很令⼈头疼

选取枢纽元:

三数取中法
选取a[left],a[mid],a[right]的中位数作为枢纽元
避免数组基本有序时时间复杂度退化成⼆次
同时保证a[left] ≤ a[mid] ≤ a[right]
⽅便下⼀步处理

分割策略:

  1. 将枢纽元(a[mid])与最后⼀个元素(a[right - 1])交换
  2. l从第⼀个元素(left + 1)开始,r从倒数第⼆个元素(right - 2)开始
  3. 当l在r的左边时,将l右移,移过小于枢纽元的元素,将r左移,移过大于枢纽元
    的元素
    当l和r停止时,如果l仍在r的左边,则交换这两个元素
  4. 当l和r交错后,将枢纽元与l位置元素互换
    避免数组元素大小相同时时间复杂度退化成⼆次

小数组优化:

对于小数组使用插入排序

#define CUTOFF 10
int mid3(int left, int right) {     //三数取中
	int mid = (left + right) / 2;
	if (a[left] > a[mid]) {
		int t = a[left];
		a[left] = a[mid];
		a[mid] = t;
	}
	if (a[left] > a[right]) {
		int t = a[left];
		a[left] = a[right];
		a[right] = t;
	}
	if (a[mid] > a[right]) {
		int t = a[mid];
		a[mid] = a[right];
		a[right] = t;
	}

	int t = a[mid];
	a[mid] = a[right - 1];
	a[right - 1] = t;

	return a[right - 1];
}
//insertsort()见插入排序
void quicksort(int left, int right) {
	if (left + CUTOFF <= right) {
		int x = mid3(left, right);
		int l = left, r = right - 1;
		for ( ; ; ) {
			while (a[++l] < x);
			while (a[--r] > x);
			if (l < r) {
				int t = a[l];
				a[l] = a[r];
				a[r] = t;
			}
			else break;
		}
		int t = a[l];
		a[l] = a[right - 1];
		a[right - 1] = t;
	
		quicksort(left, l - 1);
		quicksort(l + 1, right);
	}
	else
		insertsort(left, right - left + 1);
}

8. 桶排序

线性时间排序算法
*代码略

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值