[算法]十大排序

排序

基于插入的排序:

  • 直接插入排序算法
  • shell(希尔)排序
    基于交换的排序:
  • 冒泡排序
  • 快速排序
    基于选择的排序:
  • 简单选择排序
  • 堆排序
    其他的排序:
  • 归并排序
  • 基于统计的排序

直接插入排序

直接插入排序优化出两个算法

  • 折半插入排序
  • 2路插入排序

直接插入排序:

  • 在添加新的数据时,我们使用顺序查找的方式找到其要插入的位置,将其插入
  • 性质
    • 时间复杂度: O(n2)O(n^2)O(n2)
    • 稳定排序
    • 就地排序
    • 内部排序

折半插入排序

  • 在直接插入排序中的顺序查找换成折半查找(二分查找)
  • 优化后和没优化基本没有多少分别

二路插入排序

  • 新建一个和原数组相同大小的循环数组,然后再把元素依然插进去,可以节省一点交换元素的时间
  • 但优化后和没优化基本没有多少分别
cpp 复制代码
void straight_insert_sort()//直接插入排序
{
	int i, j, x;
	for (i = 0; i < n; i++)
	{
		x = arr[i];
		for (j = 0; j < i; j++)
			if (arr[j] > arr[i])
				break;
		for (int z = i; z > j; z--)
			arr[z] = arr[z - 1];
		arr[j] = x;
	}
}

shell(希尔)排序

希尔排序又叫缩小增量排序

理论基础

  • 插入排序在处理基本有序 的数组时,效率非常高,接近 O(n)O(n)O(n)。
  • 通过将数组按大增量分组进行插入排序,可以快速地让距离较远的元素到达其大致正确的位置,从而使整个数组宏观上变得"基本有序"。
  • 随着增量逐渐缩小,数组的有序程度越来越高,直到最后增量为1时,进行一次标准的直接插入排序,此时由于数组已基本有序,排序效率很高

定义: 在直接插入排序算法的基础上,对待排序的数组进行分组,先对每一组进行排序,然后不断缩小组数,不断排序,直到缩小到为1组

如何分组

  • 比如有9个数可以分成三组(增量), 分成[1,4,7],[2,5,8],[3,6,9]
  • 增量的选择: 不同的增量的选择, 会使得希尔排序有不同的时间复杂度, 以下给出一个可能的增量方法
    • 对n个数据进行排序: n/2->n/4->n/8->...->1

性质

  • 时间复杂度
    • 不同的增量的选择有不同的时间复杂度
  • 不稳定排序
  • 就地排序
  • 内部排序
cpp 复制代码
void shell_sort()
{
	int x,j;
	for (int k = n/2; k >= 1; k /= 2)
	{
		for (int i = k ; i < n; i++)
		{
			x = arr[i];
			for (j = i; j >= k; j -= k)
			{
				if (arr[j-k] < x)
					break;
				arr[j] = arr[j - k];
			}
			arr[j] = x;
		}
	}
}

冒泡排序

冒泡排序: 通过不断的比较两个相邻的元素,若这两个元素是乱序的,则交换位置,从而实现每趟都把最大的数据交换到最后面

性质

  • 时间复杂度: O(n2)O(n^2)O(n2)
  • 稳定排序
  • 就地排序
  • 内部排序
cpp 复制代码
void bubble_sort()
{
	for (int i = 0; i < n - 1; i++)
		for (int j = 0; j < n - 1 - i; j++)
			if (arr[j] > arr[j + 1])
				swap(arr[j], arr[j + 1]);
}

快速排序

快速排序: 分治法, 把一个相对无序的数组, 分为两个相对有序的数组, 那么分出来的两个相对有序的数组再分别运行相同的操作(即把它看做一个相对无序的数组进行处理)

  • 首先选定一个基准数x(比较的标准),把比基准数x小的数据放在x前面,把比基准数x大的数据放在后面, 排好一趟之后,x把序列分成了两部分,这两部分可还都是乱序,再分别对这两部分进行快速排序

性质:

  • 时间复杂度: O(nlog⁡n)O(n\log n)O(nlogn)
  • 就地排序
  • 不稳定排序
  • 内部排序
cpp 复制代码
void quick_sort(int arr[],int l, int r)
{
	if (l >= r)
		return;
 
	int x = arr[l+r>>1], i = l - 1, j = r + 1; 
	while (i < j)
	{
		do i++; while (arr[i] < x);
		do j--; while (arr[j] > x);
		if (i < j) swap(arr[i], arr[j]);
	}

	quick_sort(arr,l, j), quick_sort(arr,j + 1, r);
}

简单选择排序

简单选择排序: 每次从待排序区中,选择一个最小的数,放在待排序区的第一个位置,从而实现升序排列

性质

  • 时间复杂度: O(n2)O(n^2)O(n2)
  • 不稳定排序
  • 就地排序
  • 内部排序
cpp 复制代码
void select_sort()
{
	for (int i = 0; i < n - 1; i++)
	{
		int pos = i;
		for (int j = i; j < n; j++)
			if (a[pos] > a[j])
				 pos = j;
		swap(a[i], a[pos]);
	}
}

堆排序

堆排序只是对简单选择排序的一个优化,找待排序区的最小一个数的时间复杂度从O(n)到O(log n) , 重点是堆的概念(上一篇有说)

cpp 复制代码
#include <iostream>
using namespace std;

int a[105];

void down_adjust(int a[], int i, int n)
{
	int father = i, child = 2 * i;
	while (child <= n)
	{
		if (child + 1 <= n && a[child] > a[child + 1])
			child = child + 1;
		if (a[father] <= a[child])
			return;
		else
		{
			swap(a[father], a[child]);
			father = child;
			child = father * 2;
		}
	}
}

int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (int i = n / 2; i >= 1; i--)
		down_adjust(a, i, n);

	for (int i = 1,j=n; i <= n; i++,j--)
	{
		cout << a[1] << " ";
		a[1] = a[j];
		down_adjust(a, 1, j-1);
	}
	return 0;
}

归并排序

思路: 分治法, 把两个有序的数组合并为一个有序的数组

  • 先将所有记录完全分开,然后两两合并,在合并的过程中将其排好序,最终能够得到一个完整的有序表

性质:

  • 时间复杂度: O(nlog⁡n)O(n\log n )O(nlogn)
  • 非就地排序
  • 稳定排序
cpp 复制代码
void merge_sort(int a[], int l, int r)
{
	if (l >= r)return;
	int middle = l + (r - l) / 2;
	merge_sort(a, l, middle), merge_sort(a, middle + 1, r);

	int i = l, j = middle + 1, k = 0;
	while (i <= middle && j <= r)
	{
		if (a[i] <= a[j])
			temp[k++] = a[i++];
		else
			temp[k++] = a[j++];
	}
	while (i <= middle)temp[k++] = a[i++];
	while (j <= r)temp[k++] = a[j++];

	for (int i = l, j = 0; i <= r; i++, j++)
		a[i] = temp[j];
}

基于统计的排序

  • 计数排序: 统计每个数出现的次数,然后直接按次数输出
  • 桶排序: 把数放在桶中,然后再对每一个桶进行排序
  • 基数排序: 和桶排序差不多,但对每一个位数进行一次排序,排序一定要稳定
相关推荐
yuuki2332333 小时前
【数据结构】顺序表+回调函数
c语言·数据结构·后端
大数据张老师3 小时前
数据结构——堆排序
数据结构·算法·排序算法
画个逗号给明天"3 小时前
C++十大排序算法
数据结构·c++·排序算法
仰泳的熊猫3 小时前
LeetCode:268. 丢失的数字
数据结构·c++·算法·leetcode
小龙报4 小时前
《算法通关指南数据结构和算法篇(3)--- 栈和stack》
开发语言·数据结构·c++·算法·创业创新·学习方法·visual studio
CoovallyAIHub5 小时前
智能“下沉”:边缘AI,更低功耗、更快响应、更强隐私,YOLO26只是开始
深度学习·算法·计算机视觉
yy_xzz5 小时前
【数据结构】大话单链表
数据结构·链表
Lear5 小时前
【链表】LeetCode 142.环形链表
算法
CoovallyAIHub5 小时前
2025目标检测模型全景图:从RF-DETR到YOLOv12,谁主沉浮?
深度学习·算法·计算机视觉