【C++算法竞赛】排序算法

我是黑洞极客,欢迎来到算法竞赛系列!欢迎了解关注专栏【算法竞赛】

在开始之前,我先推荐两个算法学习网站(强推!):visualgo.net 和 oi-wiki.org

 温馨提示:结合算法可视化动画食用更佳 

排序算法

排序算法是最常用的算法之一

所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。排序算法,就是如何使得记录按照要求排列的方法。排序算法在很多领域得到相当地重视,尤其是在大量数据的处理方面。——百度百科

简单地说,常见的数组排序就是把这些数从小到大排列起来。

常见排序算法:

冒泡排序、插入排序、选择排序、快速排序、堆排序、桶排序、基数排序、计数排序、希尔排序、归并排序等

(加粗的是本文将要介绍的)

算法对比

不同的排序算法有不同的优劣处,正确选择算法可以让程序效率有效提升!(下面表格很重要!)

名称时间复杂度最好时间复杂度最坏时间复杂度空间复杂度稳定性
冒泡排序O(n^2)O(n)O(n^2)O(1)稳定
插入排序O(n^2)O(n)O(n^2)O(1)稳定
选择排序O(n^2)O(n^2)O(n^2)O(1)不稳定
堆排序O(nlogn)O(nlogn)O(nlogn)O(1)不稳定
桶排序O(n+k)O(n+k)O(n^2)O(n+k)稳定
基数排序O(n*k)O(n*k)O(n*k)O(n+k)稳定
计数排序O(n+k)O(n+k)O(n+k)O(k)稳定
快速排序O(nlogn)O(nlogn)O(n^2)O(logn)不稳定
希尔排序O(nlogn)O(nlog^2n)O(nlog^2n)O(1)不稳定
归并排序O(nlogn)O(nlogn)O(nlogn)O(n)稳定

冒泡排序

传送我的另一篇文章:

C++算法学习:冒泡排序 Bubble Sort-CSDN博客

插入排序

插入排序(Insertion Sort),是一个常见的排序算法,平均时间复杂度为O(n^2)。

顾名思义,插入排序就是把每一个元素插入进数组里适当的位置,在插入的过程中进行比较。

一个与插入排序相同的操作是打扑克牌时,从牌桌上抓一张牌,按牌面大小插到手牌后,再抓下一张牌。是不是好理解了?

1、以第一个元素为一个新数组

2、取出下一个元素,与新数组的每个元素进行比较

3、如果前一个元素<=它且后一个元素>=它,那这就是它的位置

4、从后往前每个位置替换成前面的元素,效果是所有新元素后的元素后移

5、循环此过程,直到所有元素取完,排序结束 

void InsertSort(int* arr, int n)
{
	for (int i = 0; i < n - 1; ++i)
	{
		int end = i;
		int tem = arr[end + 1];
		while (end >= 0)
		{
			if (tem < arr[end])
			{
				arr[end + 1] = arr[end];
				end--;
			}
			else break;
		}
		arr[end  + 1] = tem;
	}
}

选择排序

选择排序(Selection Sort),就是在每一轮遍历中找出未排序的最小值(或最大值),然后将其与第一个(或最后一个)元素交换。也可以在一轮中同时找出最大和最小值,将效率翻倍。

void selection_sort(int arr[], int len)
{
    int i,j;
    for (i = 0 ; i < len - 1 ; i++) {
        int min = i;
        for (j = i + 1; j < len; j++){ // 遍历未排序的元素
            if (arr[j] < arr[min]){
                min = j; // 最小值
            }
        }
        swap(arr[min], arr[i]);
    }
}

桶排序

桶排序(Bucket Sort),适用于待排序数据值域较大但分布比较均匀的情况。

1、设置一个定量的数组当作空桶;

2、遍历序列,并将元素一个个放到对应的桶中;

3、对每个不是空的桶进行排序;

4、从不是空的桶里把元素再放回原来的序列中。 

有点复杂,谨慎使用 

#include<stdio.h>
int main() {
    int book[1001], i, j, t;
    // 初始化桶数组
    for(i = 0; i <= 1000; i++) {
      book[i] = 0;
    }
    // 输入
    scanf("%d", &n);
    for(i = 1; i <= n; i++){
        scanf("%d", &t);
        // 计数
        book[t]++;
    }
    // 输出
    for(i = 1000; i >= 0; i--){
        for(j = 1; j <= book[i]; j++){
            printf("%d", i);
        }
    }
    return 0;
}

希尔排序

希尔排序(Shell's Sort),是插入排序的改进版本。

1、将待排序序列分为若干子序列(每个子序列的元素在原始数组中间距相同);

2、对这些子序列进行插入排序;

3、减小每个子序列中元素之间的间距,重复上述过程直至间距减少为1。

void shell_sort(int arr[], int len) {
    int increasement = len;
	int i, j, k;
	do
	{
		// 确定分组的增量
		increasement = increasement / 3 + 1;
		for (i = 0; i < increasement; i++)
		{
			for (j = i + increasement; j < len; j += increasement)
			{
				if (arr[j] < arr[j - increasement])
				{
					int temp = arr[j];
					for (k = j - increasement; k >= 0 && temp < arr[k]; k -= increasement)
					{
						arr[k + increasement] = arr[k];
					}
					arr[k + increasement] = temp;
				}
			}
		}
	} while (increasement > 1);
}

快速排序

快速排序(Quick Sort),正如它的名字,他是排序算法中比较快的一个,算法复杂度为O(nlogn),也是C++中 sort 函数所用的排序算法。 快速排序运用了分治的方式。

1、将数列划分为两部分(要求保证相对大小关系);

2、递归到两个子序列中分别进行快速排序;

3、不用合并,因为此时数列已经完全有序。

void QuickSort(int arr[], int start, int end)
{
	if (start >= end) return;
	int i = start;
	int j = end;
	// 基准数
	int baseval = arr[start];
	while (i < j) {
		// 从右向左找比基准数小的数
		while (i < j && arr[j] >= baseval) j--;
		if (i < j) {
			arr[i] = arr[j];
			i++;
		}
		// 从左向右找比基准数大的数
		while (i < j && arr[i] < baseval) i++;
		if (i < j) {
			arr[j] = arr[i];
			j--;
		}
	}
	// 把基准数放到i的位置
	arr[i] = baseval;
	// 递归
	QuickSort(arr, start, i - 1);
	QuickSort(arr, i + 1, end);
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值