排序算法部分总结

1、插入排序

1.1 算法步骤

将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

1.2算法实现
clike 复制代码
//插入排序 
void Insert_Sort(int num[], int n)
{
	int i, j;
	for (i = 1; i < n; i++)
	{
		int key = num[i];
		j = i - 1;
		while ((j >= 0) && (key < num[j])) {
			num[j + 1] = num[j];
			j--;
		}
		num[j + 1] = key;
	}
}
最好O(n) 最差O(n^2)
1.3优化
clike 复制代码
// 折半插入排序
void Insert_Sort_half(int num[], int n)
{
	int i, j;
	for (i = 1; i < n; i++)
	{
		int key = num[i];
		int left = 0;
		int right = i - 1;
		while (left <= right)
		{
			int mid = left + (right - left) / 2;
			if (num[mid] < key)
			{
				left = mid + 1;
			}
			else
			{
				right = mid - 1;
			}
		}
		for (j = i - 1; j >= left; j--)
		{
			num[j + 1] = num[j];
		}
		num[left] = key;
	}
}

2、希尔排序

2.1算法步骤

希尔排序算法的步骤如下:

选择增量序列:首先选择一个增量序列,通常是将数组长度不断除以 2,直到增量为 1。常见的增量序列包括希尔增量序列、Hibbard 增量序列、Sedgewick 增量序列等。

按增量分组:根据所选的增量,将数组分成多个子序列。每个子序列包含相距为增量的元素。例如,如果增量为 3,则第一个子序列包含数组中下标为 0、3、6、9...的元素,第二个子序列包含数组中下标为 1、4、7、10...的元素,以此类推。

对每个子序列进行插入排序:对每个子序列进行插入排序。即,将每个子序列视为一个独立的数组,使用插入排序算法对其进行排序。

缩小增量:逐步缩小增量,重复步骤 2 和步骤 3,直到增量为 1。

最后一次排序:当增量为 1 时,进行最后一次排序。此时,整个数组被视为一个序列,进行一次插入排序。

2.2算法实现
clike 复制代码
// 希尔排序

void Shell_Sort(int num[], int n)
{
	int gap = n / 2;
	while (gap > 0)
	{
		for (int i = gap; i < n; i++)
		{
			int temp = num[i];
			int j = i;
			while (j >= gap && num[j - gap] > temp)
			{
				num[j] = num[j - gap];
				j -= gap;
			}
			num[j] = temp;
		}
		gap /= 2;
	}
}

3、冒泡排序

3.1算法步骤

冒泡排序算法的步骤如下:

比较相邻元素:从数组的第一个元素开始,依次比较相邻的两个元素,如果第一个元素比第二个元素大(升序排序),则交换它们的位置。

一轮排序完成后,最大(或最小)的元素会被移动到数组末尾:经过一轮比较和交换操作后,数组中最大(或最小)的元素会被移动到数组的末尾位置。

重复以上步骤:重复执行步骤 1 和步骤 2,直到所有元素都按照指定的顺序排列好。

优化:通常情况下,每一轮排序后都会确定一个最大(或最小)的元素的位置,因此在下一轮排序时,可以不考虑已经确定位置的元素。

终止条件:如果在一轮排序中没有发生任何交换操作,即数组已经完全有序,可以提前结束排序。

3.2算法实现
clike 复制代码
// 冒泡排序
void Bubble_Sort(int num[], int n)
{
	for (int i = 1; i < n; i++)
	{
		for (int j = i; j < n; j++)
		{
			if (num[j] < num[j - 1])
			{
				int temp = num[j];
				num[j] = num[j - 1];
				num[j - 1] = temp;
			}
		}
	}
}

4、选择排序

4.1算法步骤

选择排序是一种简单直观的排序算法,它的步骤如下:

遍历数组: 从数组的第一个元素开始,依次遍历到倒数第二个元素。

找到最小元素: 在当前遍历到的元素及其后面的所有元素中,找到最小的元素。

交换位置: 将找到的最小元素与当前遍历到的元素交换位置。

继续遍历: 继续从下一个位置开始重复以上步骤,直到遍历完整个数组。

4.2算法实现

clike 复制代码
//选择排序
void Select_Sort(int num[], int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int min = i;
		for (int j = i + 1; j < n; j++)
		{
			if (num[j] < num[min])
				min = j;

		}

		int temp = num[i];
		num[i] = num[min];
		num[min] = temp;
	}
}

5、归并排序

5.1算法步骤

归并排序是一种经典的分治算法,其步骤如下:

分解: 将原始数组递归地分成两个子数组,直到每个子数组只包含一个元素或者是空数组。

解决: 对每个子数组进行排序,如果子数组只包含一个元素,则认为它已经是有序的。

合并: 合并两个已排序的子数组,产生一个新的有序数组。合并过程中,通过比较两个子数组的首元素,选择较小的元素放入新数组,并且移动对应子数组的指针。

递归地合并: 重复上述步骤,直到所有子数组都被合并成一个整体有序的数组。

5.2算法实现
clike 复制代码
// 归并排序
void Merge(int num[], int l, int q, int r)
{
	int n1 = q - l + 1; // 计算左子数组的长度
	int n2 = r - q;     // 计算右子数组的长度
	int* L = new int[n1];
	int* R = new int[n2];

	// 将原数组分成左右两个子数组
	for (int i = 0; i < n1; i++)
		L[i] = num[l + i];
	for (int j = 0; j < n2; j++)
		R[j] = num[q + 1 + j];

	// 合并左右两个子数组到原数组
	int i = 0, j = 0, k = l;
	while (i < n1 && j < n2)
	{
		if (L[i] <= R[j])
		{
			num[k] = L[i];
			i++;
		}
		else
		{
			num[k] = R[j];
			j++;
		}
		k++;
	}

	// 将剩余元素拷贝到原数组
	while (i < n1)
	{
		num[k] = L[i];
		i++;
		k++;
	}
	while (j < n2)
	{
		num[k] = R[j];
		j++;
		k++;
	}

	// 释放临时数组
	delete[] L;
	delete[] R;
}

void Merge_Sort(int num[], int l, int r)
{
	if (l < r)
	{
		int q = (l + r) / 2;
		Merge_Sort(num, l, q);
		Merge_Sort(num, q + 1, r);
		Merge(num, l, q, r);
	}
}

6、快速排序

6.1算法步骤

快速排序的基本步骤:

选择基准值: 从数组中选择一个元素作为基准值。通常选择第一个元素、最后一个元素或者随机一个元素作为基准值。

分区操作: 将数组中小于基准值的元素移到基准值的左侧,大于基准值的元素移到基准值的右侧。这一步通常使用双指针法实现。

递归排序: 对基准值左右两侧的子数组分别递归地执行上述步骤,直到子数组的大小为 0 或 1,即已经有序。

合并结果: 不需要合并操作,因为在分区操作中,元素已经移动到了正确的位置。

6.2代码实现
clike 复制代码
//快速排序
void swap(int& a, int& b)
{
	int temp = a;
	a = b;
	b = temp;
}

int partition(int num[], int low, int high)
{
	int pivot = num[high];
	int i = (low - 1);

	for (int j = low; j <= high - 1; j++)
	{
		if (num[j] <= pivot)
		{
			i++;
			swap(num[i], num[j]);
		}
	}
	swap(num[i + 1], num[high]);
	return (i + 1);
}
void quick_Sort(int num[], int low, int high)
{
	if (low < high) {
		// pi 是划分的索引,arr[pi] 正好在其正确的位置
		int pi = partition(num, low, high);

		// 分别对划分的两个子数组进行快速排序
		quick_Sort(num, low, pi - 1);
		quick_Sort(num, pi + 1, high);
	}
}

7、计数排序

7.1算法步骤:

算法的步骤如下:

(1)找出待排序的数组中最大和最小的元素

(2)统计数组中每个值为i的元素出现的次数,存入数组C的第i项

(3)对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)

(4)反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

7.2算法实现
clike 复制代码
//计数排序
void countSort(std::vector<int>& arr)
{
	if (arr.empty())return;
	//找到数组中的最大值和最小值
	int max_element = *std::max_element(arr.begin(), arr.end());
	int min_element = *std::min_element(arr.begin(), arr.end());

	//计算数组的大小
	int count_size = max_element - min_element + 1;
	//创建技术数组并初始化为0
	std::vector<int>count(count_size, 0);

	for (int num : arr)
	{
		count[num - min_element]++;
	}

	//根据计数重新构建数组
	int index = 0;
	for (int i = 0; i < count_size; i++)
	{
		while (count[i] > 0)
		{
			arr[index++] = i + min_element;
			count[i]--;
		}
	}
}

8、桶排序

8.1算法实现
clike 复制代码
//桶排序
void bucketSort(std::vector<int>& arr) {
	if (arr.empty()) return;

	// 找到数组中的最大值和最小值
	int max_element = *std::max_element(arr.begin(), arr.end());
	int min_element = *std::min_element(arr.begin(), arr.end());

	// 计算桶的数量,可以根据具体情况调整桶的数量
	int bucket_count = max_element - min_element + 1;

	// 创建桶,并初始化为空
	std::vector<std::vector<int>> buckets(bucket_count);

	// 将元素放入对应的桶中
	for (int num : arr) {
		int index = num - min_element;
		buckets[index].push_back(num);
	}

	// 对每个桶中的元素进行排序,这里使用了插入排序
	for (auto& bucket : buckets) {
		sort(bucket.begin(), bucket.end());
	}

	// 将桶中的元素按顺序放回原始数组中
	int index = 0;
	for (auto& bucket : buckets) {
		for (int num : bucket) {
			arr[index++] = num;
		}
	}
}
相关推荐
Mephisto.java几秒前
【力扣 | SQL题 | 每日三题】力扣175, 176, 181
sql·算法·leetcode
木向9 分钟前
leetcode第十二题:整数转罗马数字
c++·算法·leetcode·职场和发展
繁星璀璨G14 分钟前
C++11标准模板(STL)- 常用数学函数 - 计算e的给定幂 (ex)(std::exp, std::expf, std::expl)
开发语言·c++·算法·stl·计算e的给定幂
the sun3414 分钟前
C++红黑树
c++
X² 编程说20 分钟前
14.面试算法-字符串常见算法题(三)
java·数据结构·后端·算法·面试
程序猿练习生21 分钟前
C++速通LeetCode中等第20题-随机链表的复制(三步简单图解)
c++·leetcode·链表
S01d13r30 分钟前
LeetCode 每周算法 6(图论、回溯)
算法·leetcode·图论
阑梦清川43 分钟前
C++初阶-list用法总结
开发语言·c++·stl·list
秋落风声44 分钟前
C++---类与对象一
c++
程序员波特1 小时前
初识算法
数据结构·算法·leetcode