1、冒泡排序(Bubble Sort)
void bubbleSort(int arr[], int n) {
for (int i = 0; i < n-1; ++i) {
for (int j = 0; j < n-i-1; ++j) {
if (arr[j] > arr[j+1]) {
std::swap(arr[j], arr[j+1]);
}
}
}
}
2、选择排序(Selection Sort)
void selectionSort(int arr[], int n) {
for (int i = 0; i < n-1; ++i) {
int minIdx = i;
for (int j = i+1; j < n; ++j) {
if (arr[j] < arr[minIdx]) {
minIdx = j;
}
}
std::swap(arr[i], arr[minIdx]);
}
}
3、插入排序(Insertion Sort)
具体步骤如下:
- 从待排序部分选取一个元素(通常从左到右逐个选取)。
- 将选取的元素与已排序部分从右往左比较,找到合适的插入位置。
- 将选取的元素插入到找到的位置,然后继续处理下一个待排序元素。
- 不断重复上述插入步骤,直到所有待排序元素都插入到已排序部分,最终得到一个完全有序的数组。
void insertionSort(int arr[], int n) {
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j+1] = arr[j];
--j;
}
arr[j+1] = key;
}
}
4、希尔排序(Shell Sort)
希尔排序的步骤如下:
-
选择增量序列: 首先选择一个增量序列,通常是初始间隔为数组长度的一半,然后逐步缩小增量。常用的增量序列包括希尔增量(间隔逐渐减半)、Hibbard增量等,你可以根据实际情况选择合适的增量序列。
-
分组插入排序: 将数组按照选定的增量进行分组,形成多个子序列。对每个子序列分别进行插入排序,即将子序列中的元素逐个插入到正确的位置。
-
逐步缩小增量: 重复上述步骤,逐步缩小增量,直到增量为1。这样就会逐渐将数组整体有序。
void shellSort(int arr[], int n)
{
for (int gap = n/2; gap > 0; gap /= 2)
{
for (int i = gap; i < n; ++i)
{
int temp = arr[i];
int j;
for (j = i; j >= gap && arr[j-gap] > temp; j -= gap)
{
arr[j] = arr[j-gap];
}
arr[j] = temp;
}
}
}
5、归并排序(Merge Sort)
void merge(int arr[], int left, int mid, int right)
{
int n1 = mid - left + 1;
int n2 = right - mid;
int L[n1], R[n2];
for (int i = 0; i < n1; ++i)
{
L[i] = arr[left + i];
}
for (int j = 0; j < n2; ++j)
{
R[j] = arr[mid + 1 + j];
}
int i = 0, j = 0, k = left;
while (i < n1 && j < n2)
{
if (L[i] <= R[j])
{
arr[k] = L[i];
++i;
}
else
{
arr[k] = R[j];
++j;
}
++k;
}
while (i < n1)
{
arr[k] = L[i];
++i;
++k;
}
while (j < n2)
{
arr[k] = R[j];
++j;
++k;
}
}
void mergeSort(int arr[], int left, int right)
{
if (left < right)
{
int mid = left + (right - left) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left,mid, right);
}
}
6、快速排序(Quick Sort)
int partition(int arr[], int low, int high)
{
int pivot = arr[high];
int i = low - 1;
for (int j = low; j <= high - 1; ++j)
{
if (arr[j] < pivot)
{
++i;
swap(arr[i], arr[j]);
}
}
swap(arr[i+1], arr[high]);
return i + 1;
}
void quickSort(int arr[], int low, int high)
{
if (low < high)
{
int pi = partition(arr, low, high);
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
7、堆排序(Heap Sort)
堆排序的具体步骤:
-
建立最大堆(Max Heap): 将待排序的数组看作一个二叉堆,首先需要将这个数组转换成一个最大堆。这可以通过从最后一个非叶节点开始,对所有非叶节点进行下沉操作(即将节点与其较大的子节点交换),直到整个数组满足最大堆的性质。
-
堆排序: 建立最大堆后,数组的根节点(即最大值)位于堆顶。将堆顶元素与堆的最后一个元素交换位置,然后将堆的大小减一(即排除最后一个元素)。此时,堆的根节点可能破坏了最大堆的性质,因此需要将根节点进行下沉操作,以恢复最大堆的性质。重复这个过程,直到堆的大小缩减到1,排序完成。
#include <stdio.h>
#include <iostream>
#include <vector>
#include <algorithm> //堆的相关算法
#include <functional>
using namespace std;
// 传入数组a和下标i,i的左右子树都满足最大堆的性质,函数将a整体调整为最大堆
void heap_down(vector<int> &a, int i)
{
while (i < a.size())
{
int left = 2 * i + 1; // 计算i的左子节点下标
int right = 2 * i + 2; // 计算i的右子节点下标
int maxium = i; // 设置maxium存储i和左右子节点较大节点的下标,初始化i
// 如果左子树存在且a[maxium] 小于 a[left]
if (left < a.size() && a[maxium] < a[left])
{
maxium = left;
}
// 如果右子树存在且a[maxium] 小于a[right]
if (right < a.size() && a[maxium] < a[right])
{
maxium = right;
}
if (maxium == i) // 如果此时maxium仍然等于i
{
break; // 说明a[i]比左右子节点都打,后面就不需要再调整了,跳出循环
}
// 交换a[i]和a[maxium]
int tmp = a[i];
a[i] = a[maxium];
a[maxium] = tmp;
i = maxium; // 将i指向maxium,继续向下调整
}
}
void make_heap(vector<int> &a)
{
for (int i = a.size(); i >= 0; i--)
{
heap_down(a, i); // 从后向前调用heap_down调整数组a的每个元素
}
}
int main()
{
vector<int> a;
a.push_back(1);
a.push_back(2);
a.push_back(3);
a.push_back(4);
a.push_back(5);
a.push_back(6);
a.push_back(7);
a.push_back(8);
a.push_back(9);
a.push_back(10);
cout << " before make_heap:" << endl;
for (int i = 0; i < a.size(); i++)
{
cout << a[i] << " ";
}
cout << endl;
make_heap(a);
cout << " make_heap:" << endl;
for (int i = 0; i < a.size(); i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
8、计数排序(Counting Sort)
void countingSort(int arr[], int n) {
int max = arr[0];
for (int i = 1; i < n; ++i) {
if (arr[i] > max) {
max = arr[i];
}
}
int count[max + 1];
int output[n];
for (int i = 0; i <= max; ++i) {
count[i] = 0;
}
for (int i = 0; i < n; ++i) {
++count[arr[i]];
}
for (int i = 1; i <= max; ++i) {
count[i] += count[i-1];
}
for (int i = n - 1; i >= 0; --i) {
output[count[arr[i]] - 1] = arr[i];
--count[arr[i]];
}
for (int i = 0; i < n; ++i) {
arr[i] = output[i];
}
}
9、桶排序(Bucket Sort)
void insertionSort(std::vector<int>& arr) {
int n = arr.size();
for (int i = 1; i < n; ++i) {
int key = arr[i];
int j = i - 1;
while (j >= 0 && arr[j] > key) {
arr[j + 1] = arr[j];
--j;
}
arr[j + 1] = key;
}
}
void bucketSort(int arr[], int n) {
std::vector<std::vector<int>> buckets(n);
// 将元素分配到不同的桶中
for (int i = 0; i < n; ++i) {
int bucketIndex = n * arr[i];
buckets[bucketIndex].push_back(arr[i]);
}
// 对每个桶中的元素进行插入排序
for (int i = 0; i < n; ++i) {
insertionSort(buckets[i]);
}
// 将排序好的元素合并到原始数组中
int index = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < buckets[i].size(); ++j) {
arr[index++] = buckets[i][j];
}
}
}
10、基数排序(Radix Sort)
int getMax(int arr[], int n) {
int max = arr[0];
for (int i = 1; i < n; ++i) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
void countSort(int arr[], int n, int exp) {
int output[n];
int count[10] = {0};
for (int i = 0; i < n; ++i) {
count[(arr[i] / exp) % 10]++;
}
for (int i = 1; i < 10; ++i) {
count[i] += count[i-1];
}
for (int i = n - 1; i >= 0; --i) {
output[count[(arr[i] / exp) % 10] - 1] = arr[i];
count[(arr[i] / exp) % 10]--;
}
for (int i = 0; i < n; ++i) {
arr[i] = output[i];
}
}
void radixSort(int arr[], int n) {
int max = getMax(arr, n);
for (int exp = 1; max / exp > 0; exp *= 10) {
countSort(arr, n, exp);
}
}