十大排序总结(一,简易篇)

1.冒泡排序
大一就学的必备技能,最简单的排序时i,j都从0-n进行判断swap,虽然也是O(n2)但这种排序低级到无法进入我们的十大排序中,所以要对其进行一下优化,就是i从0-n,但j可以从n-1到i,这样节省了不必要的操作。
冒泡就是说每个数与后面的比较,这样每次就会把未排序的最大的浮到后面。最坏(完全乱序,退化到刚才说的不入流方法)和平均时间复杂度为O(n2),最好就是O(n)(本来就有序,一趟完成),空间复杂度为O(1)。

void bubble(vector<int>& a) {
	int n = a.size();
	for (int i = 0; i < n-1; i++) //趟数
	{
		for (int j = n-2; j >=0; j--) //次数
		{
			if (a[j] > a[j + 1])
			{
				swap(a[j], a[j + 1]);
			}
		}
	}
}

2.选择排序
就是每次从未排序数组中选择一个最小的放在已排序的最右边,思路很简单,就是每次都得遍历完全部数组才能找到最小的。最好最坏平均时间复杂度均为O(n2),空间复杂度为O(1)。
选择排序的元素的比较次数与初始序列无关,直接选择排序的时间复杂度与初始序列无关的。

void select(vector<int>&a)
{
	int n = a.size();
	for (int i = 0; i <n; i++) {
		int index = i;
		for (int j = i + 1; j <n; j++) {
			if (a[j] < a[index])
				index = j;
		}
		swap(a[i], a[index]);
	}
}

3.插入排序
顾名思义,就是将当前遍历到的数插入到已排序数组里。它与选择排序相比,不需要每趟走完数组,只要找到合适的位置就可以结束该次循环了
时间复杂度为O(n2),最好O(n)。空间O(1).
直接插入排序

void insert(vector<int>& a) {
	int n = a.size();
	for (int i = 0; i < n; ++i) {
		for (int j = 0; j < i; ++j) {
			if (a[i] < a[j])
				swap(a[i], a[j]);
		}
	}
}

折半插入:就是在插入时采用二分法来定位该插到哪,节省比较次数。

void binInsert(vector<int>& a) {
	int low, high, m, temp, i, j;
	for (i = 1; i < a.size(); i++) {
		//折半查找应该插入的位置
		low = 0;
		high = i - 1;
		while (low <= high) {
			m = (low + high) / 2;
			if (a[m] > a[i])
				high = m - 1;
			else
				low = m + 1;
		}
		//统一移动元素,然后将这个元素插入到正确的位置
		temp = a[i];
		for (j = i; j > high + 1; j--) {
			a[j] = a[j - 1];
		}
		a[high + 1] = temp;
	}
}

4.希尔排序
希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。
我们来看下希尔排序的基本步骤,在此我们选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择我们可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,我们选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处我们做示例使用希尔增量。
时间复杂度O(nlogn)或O(n根号n),空间复杂度O(1)。

void shellInsert(vector<int>& a,int d) {
       int n = a.size();
       for (int t=d;t<n;++t)
       {
              int i = t - d;
              int tmp = a[t];
              while (i >= 0 && a[i] > tmp) {
                     a[i + d] = a[i];
                     i -= d;
              }
              if (i != t - d)
                     a[i + d] = tmp;
       }
}
void shellSort(vector<int>& a) {
       int n = a.size();
       int d = n / 2;    //初始增量设为数组长度的一半
       while (d >= 1)
       {
              shellInsert(a, d);
              d = d / 2;    //每次增量变为上次的二分之一
       }
}

5.计数排序
计数排序是一种线性排序算法,不需要进行比较,时间复杂度为O(n)。(注意是计数排序不是基数排序,两者不同)
基本思想是:对于每个元素x,找出比x小的数的个数,从而确定x在排好序的数组中的位置。此算法需要辅助数组,是以空间换时间。
其实就是桶排序的优化,限制并计算好了额外空间的最佳大小。

void CountSort(vector<int> &arr, int maxVal) {
	int len = arr.size();
	if (len < 1)
		return;
	vector<int> count(maxVal+1, 0);
	vector<int> tmp(arr);
	for (auto x : arr)
		count[x]++;
	for (int i = 1; i <= maxVal; ++i)
		count[i] += count[i - 1];
	for (int i = len - 1; i >= 0; --i) {
		arr[count[tmp[i]] - 1] = tmp[i];
		count[tmp[i]]--;				//注意这里要减1
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值