十大排序(c++)

排序是很常见,其实一般竞赛是直接用sort就好了, 但是有时候我们会遇到一些题目, 他需要一些排序算法的思想,so today i 写一篇;

1. 冒泡排序

最最简但的排序, 优点是好写,稳定, 缺点就是太慢,简单不赘述了。

#include <bits/stdc++.h>
using namespace std;
void bubblesort(int a[], int len){
	for (int i = 0; i < len - 1; i ++){
		for (int j = 0 ; j < len - i - 1; j ++){
			if (a[j] > a[j + 1]){
				swap(a[j], a[j + 1]);
			}
		}
	}
}
int main (){
	int a[] = {-1, -2, 0,7,-89,1000};
	int len = sizeof(a) / sizeof(a[0]);
	bubblesort(a, len);
	for (int i = 0 ; i <= len - 1; i ++){
		cout << a[i] << " ";
	}
	return 0;
} 

2.选择排序

从i的右边找到一个比a[i]小的数跟a[i]交换位置, 以此类推 时间复杂度n^2

#include <bits/stdc++.h>
using namespace std;
void selection_sort(int a[], int len){
	for (int i = 0; i < len - 1; i ++){
		int temp = i;
		for (int j = i + 1; j < len; j ++){
			//cout << "a[" << j << "] = " << a[j] << "  a[" << i << "] = " << a[i] << endl;
			if (a[j] < a[temp]) {
				temp = j;
				//cout << "temp = " << temp << endl;
			}
		}
		swap(a[temp], a[i]);
	}
}
int main (){
	int a[] = {4,3,2,1};
	int len = sizeof(a)/sizeof(a[0]);
	selection_sort(a, len);
	for (int i = 0; i <  sizeof(a)/ sizeof(a[0]); i ++){
		cout << a[i] << " ";
	}
	return 0;
}

3. 插入排序

初始假设第一个数是有序的,then让下一个数在有序数组中通过冒泡排序找到自己的位置,直到整个数组都变成有序数组。例如{4, 2, -1, 0}; 默认4是有序的, 下一个数2应该放在有序数组{4}的左边{2, 4} 无序数组变为{-1, 0}, 接下来继续操作, 直至全部遍历一遍。

#include <bits/stdc++.h>  // 插入排序; 
using namespace std;
int a[] = {6, 1, 9, 2, 3, 7, 19, 15};
int main (){
	for (int i = 1; i <= 7; i ++){  //7是数组大小 
	//第一层循环 i 指的是无序数组的第一个数 
		for (int j = i - 1; j >= 0; j --){
			//有序数组的末尾数跟无序数组第一个相比 直到找到该无序数的位置 
			if (a[j] > a[j + 1]){  // 相当于在有序数组中运用冒泡排序找到位置
				int temp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = temp;
			}
			else break; 
		}
	}
	for (int i = 0; i <= 7; i ++){
		cout << a[i] << " ";
	}
	return 0;
}

4,希尔排序

分组处理, 对每一组都进行插入排序

#include <bits/stdc++.h>  //希尔排序  
using namespace std;
// 易懂版本
int a[11] = {8, 9, 1, 7, 2, 3, 5, 4, 6, 0, 14}; // 偶数奇数没有影响,下面会解释 
int main (){
	int d = 0, len = 11;
	for (d = len / 2; d >= 1; d = d / 2) { //d表示分为多少组, 每个组内的相邻的数间隔是d 
		for (int i = 0; i < d; i ++){  // 将每一组都进行插入排序 0到d - 1 正好d个组, 所以i不能等于d 
			for (int j = i + d; j <= len - 1; j = j + d){ //无序数组的第一个数i+d 
				for (int k = j - d; k >= 0; k = k - d){
					if (a[k] > a[k + d]){
						int temp = a[k + d];
						a[k + d] = a[k];
						a[k] = temp; 
					}
					else break;
				}
			} 
		}
	}
	for (int i = 0; i <= len - 1; i ++)cout << a[i] << " ";
	return 0;
}

5. 归并排序;

归并排序是冯.诺伊曼提出的, 广泛的被应用, 运用了分治的思想,时间复杂度为nlogn, 空间复杂度为n,是一种简单高效的方法;

#include <bits/stdc++.h>
using namespace std;
void merge(int a[], int low, int mid, int hight){
	int i = low, j = mid + 1, k = 0;
	int *b = new int[hight - low + 1];
	while (i <= mid && j <= hight){
		if (a[i] >= a[j]){
			b[k ++] = a[j ++];
		}
		else{
			b[k ++] = a[i ++];
		}
	}
	while (i <= mid){
		b[k ++] = a[i ++];
	}
	while (j <= hight){
		b[k ++] = a[j ++];
	}
	k = 0;
	for (int i = low; i <= hight; i ++){
		a[i] = b[k ++];
	}
	delete []b;
}
void mergesort(int a[], int low, int hight){
	if (low < hight){
	int mid = low + (hight - low) / 2;
	mergesort(a, low, mid);
	mergesort(a, mid + 1, hight);
	merge(a, low, mid, hight);
    }
}
int main (){
	int n, a[100];
	cin >> n;
	for (int i = 0; i < n; i ++){
		cin >> a[i];
	}
	mergesort(a, 0, n - 1);
	for (int i = 0 ; i <= n - 1; i ++){
		cout << a[i] << " ";
	}
	return 0;
}

例子:图片复制于http://t.csdn.cn/eoAnM

 其中,mergesort函数就是在分, merge就是在治,也就是和并;

6. 快速排序

看这个名字就知道他有点东西,其实一般来说我们可以调用sort()函数,但是背后的源码还是要懂的,想细致的了解快排 可以看这个博客  http://t.csdn.cn/3QEkQ

// 快速排序 
#include <bits/stdc++.h>
using namespace std;
void quicksort(int a[], int left, int right){
	if (left > right) return ;
	int temp = a[left];//最左边的数据作为基准; 
	int i = left, j = right;
	while (i != j){
		while (a[j] >= temp && j > i) j --;//如果后边的元素大于等于基准元素,就 j --; 
		if (j > i) a[i ++] = a[j]; // i == j时就不用换位置了; 
		while (a[i] < temp && i < j) i ++;
		if (i < j) a[j --] = a[i];
	}
	a[i] = temp; //这里i 跟 j 相等, 用哪个都行 // 找到了基准元素的位置,其左面的元素全部小于它,右边的元素全部大于它,
	//所以它的位置一定是正确的;
	//接下来递归, 基准左面的所有元素 ,右边的所有元素; 
	quicksort(a, left, i - 1);
	quicksort(a, i + 1, right);
}
int main (){
	int a[] =  {0, 37, 43, 1, -2, -2, 788, 0};
	quicksort(a, 0, sizeof(a)/sizeof(a[0]) - 1); 
	for (int i = 0; i < sizeof(a)/sizeof(a[0]); i ++){
		cout << a[i] << " ";
	}
	return 0;
}

(图片来自蓝桥云课);

快排, 给基准元素找位置,例如,图中的49我们就假设是基准元素,通过操作找到了它的位置再递归分治找一下个, 最后就是有序的,但是切记,快速排序是不稳定的,什么是不稳定排序呢,

就是例如, {0, 0, 0, 6, 1, 2}; 排序之后 {0 ,0 ,0,1, 2, 6}; 1, 2, 6没问题

但是0不一定, 因为三个0之间的绝对位置可能变了, 第三个0可能跑第一个去了,这个在算法竞赛中基本上用不到,了解就可以了,

 7.堆排序

// 堆排序
#include <bits/stdc++.h>
using namespace std;
void max_heap(int a[], int start, int end){
	int dad = start;
	int son = dad * 2 + 1;
	while (son <= end){
		if (son + 1 <= end && a[son] < a[son + 1]) 
		son ++;
		if (a[dad] > a[son])
		return ;
		else {
			swap(a[dad], a[son]);
			dad = son;
			son = dad * 2 + 1;
		}
	}
}
void adjust_heap(int a[], int len){
	for (int i = len / 2 - 1; i >= 0; i --){
		max_heap(a, i, len - 1);
	}
	for (int i = len - 1; i >= 0; i --){
		swap(a[0], a[i]);
		max_heap(a, 0, i - 1);
	}
}
int main (){
    int a[] = {57, 61, 97, 10, 28, 87, 9, 1, 1};
    int len = sizeof(a) / sizeof(a[0]);
    adjust_heap(a, len);
    for (int i = 0; i < len; i ++){
    	cout << a[i] << " "; 
	}
	cout << endl;
	return 0;
} 

8.计数排序

适用于数据量小且最大元素最小元素大小相差不大的排序;

小数不能用

#include <bits/stdc++.h>
using namespace std;
void count_sort(int a[], int len){
	int Max = a[0], Min = a[0];
	for (int i = 0; i < len; i ++){
		Max = max(Max, a[i]);
		Min = min(Min, a[i]);
	}
	int range = Max - Min + 1;
	int *b = new int [range];
	for (int i = 0; i < range; i ++){
		b[i] = 0;
	}
	for (int i = 0; i < len; i ++){
		b[a[i] - Min] ++;
	}
	cout << endl;
	int cnt = 0;
	for (int i = 0; i < range; i ++){
		while (b[i] --){
		    a[cnt ++] = i + Min;
		}
	}

}
int main (){
	int a[] = {0, 3, 5, -1, -5, 19, 8, 8};
	int len = sizeof(a) / sizeof(a[0]);
	count_sort(a, len);
	for (int i = 0; i < len; i ++){
		cout << a[i];
		if (i != len - 1) cout << " ";
	}
	return 0;
} 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值