十大排序算法

十大排序算法

分类

  • 稳定:冒泡、插入、归并
  • 非稳定:快排,选择,希尔,堆

排序复杂度

排序时间复杂度

常见考点

🔥🔥🔥快速排序

描述

  1. 从数列中挑出一个元素,称为 “基准”(pivot)
  2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作
  3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序

代码

/*************************************************************************
> File Name:     quick_sort.cpp
> Author:        HuHan
> 微信公众号:      编程诗
> Created Time:  Wed Apr 27 20:14:10 2022
> Description:   quick sort
 ************************************************************************/
#include <iostream>
using namespace std;

int partition(int array[], int low, int high) {
    int tmp = array[low];
    while (low < high) {
        while (low < high && array[high] >= tmp) {
            --high;
        }
        array[low] = array[high];

        while (low < high && array[low] <= tmp) {
            ++low;
        }
        array[high] = array[low];
    }
    array[low] = tmp;
    return low;
}

void quickSort(int array[], int low, int high) {
    if (low < high) {
        int pivotIndex = partition(array, low, high);
        quickSort(array, low, pivotIndex - 1);
        quickSort(array, pivotIndex + 1, high);
    }
}

void randQuickSort(int array[], int low, int high) {
    if (low >= high) {
        return;
    }
    int pos = low + (rand() % (high - low));
    int l = low, h = high;
    int pivot = array[pos];

    swap(array[low], array[pos]);
    while (l < h) {
        while (array[h] >= pivot && l < h) {
            --h;
        }
        if (l < h) {
            array[l] = array[h];
            ++l;
        }
        while (array[l] <= pivot && l < h) {
            ++l;
        }
        if (l < h) {
            array[h] = array[l];
            --h;
        }
    }
    array[l] = pivot;
    randQuickSort(array, low, l-1);
    randQuickSort(array, l+1, high);
}

int main() {
    int i = 0;
    int array[] = {11, 25, 16, 2, 3, 26, 4, 91};
    int rand_arr[] = {11, 25, 16, 2, 3, 26, 4, 91};
    int len = sizeof(array) / sizeof(array[0]);

    cout << "array: ";
    for (i = 0; i < len; ++i) {
        cout << array[i] << ' ';
    }
    quickSort(array, 0, len - 1);
    cout << endl;
    cout << "sorted array: ";
    for (i = 0; i < len; ++i) {
        cout << array[i] << ' ';
    }
    cout << endl;

    randQuickSort(rand_arr, 0, len - 1);
    cout << "rand sorted array: ";
    for (i = 0; i < len; ++i) {
        cout << array[i] << ' ';
    }
    cout << endl;
    return 0;
}

🔥🔥归并排序

描述

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列;
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置;
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置;
  4. 重复步骤 3 直到某一指针达到序列尾;
  5. 将另一序列剩下的所有元素直接复制到合并序列尾。

代码

#include<iostream>
#include<vector>
using namespace std;

void mergeSort(vector<int>& k, int n){
	int i, next, left_min, left_max, right_min, right_max;
	vector<int> temp(n);

	for(int i = 1; i < n; i *= 2){//步长, 1, 2, 4, ...
		for(left_min = 0; left_min < n - i; left_min = right_max){
			//从0开始, 根据步长, 向右分组排序
			right_min = left_max = left_min + i;
			right_max = left_max + i;
			if(right_max > n){
				right_max = n;
			}
			next = 0;
			//将k[]数组中小的数据备份
			//结束条件:left或right有一个完全拷贝到temp
			while(left_min < left_max && right_min < right_max){
				if(k[left_min] < k[right_min]){
					temp[next++] = k[left_min++];
				} else{
					temp[next++] = k[right_min++];
				}
			}
			while(left_min < left_max){
				k[--right_min] = k[--left_max];
			}
			while(next > 0){
				k[--right_min] = temp[--next];
			}
		}
	}
}

int main(){
	vector<int> array = {11, 25, 16, 2, 3, 26, 4, 91};
	cout << "array:";
	for(int tmp : array) cout << tmp << ' ';
	mergeSort(array, array.size());
	cout << endl << "sorted array: ";
	for(int tmp : array) cout << tmp << ' ';
	return 0;
}

🔥🔥堆排序

堆的性质

  1. 是一棵完全二叉树
  2. 每个节点的值都大于或等于其子节点的值,为最大堆;反之为最小堆。

描述

  1. 将待排序的序列构造成一个最大堆,此时序列的最大值为根节点
  2. 依次将根节点与待排序序列的最后一个元素交换
  3. 再维护从根节点到该元素的前一个节点为最大堆,如此往复,最终得到一个递增序列
#include <iostream>
#include <algorithm>
using namespace std;
void max_heapify(int arr[], int start, int end) {
    //建立父节点指标和子节点指标
    int dad = start;
    int son = dad * 2 + 1;
    while (son <= end) { //若子节点指标在范围内才做比较
        if (son + 1 <= end && arr[son] < arr[son + 1]) //先比较两个子节点大小,选择最大的
            son++;
        if (arr[dad] > arr[son]) //如果父节点大于子节点代表调整完毕,直接跳出函数
            return;
        else { //否则交换父子内容再继续子节点和孙节点比较
            swap(arr[dad], arr[son]);
            dad = son;
            son = dad * 2 + 1;
        }
    }
}
void heap_sort(int arr[], int len) {
    //初始化,i从最后一个父节点开始调整
    for (int i = len / 2 - 1; i >= 0; i--)
        max_heapify(arr, i, len - 1);
    //先将第一个元素和已经排好的元素前一位做交换,再从新调整(刚调整的元素之前的元素),直到排序完毕
    for (int i = len - 1; i > 0; i--) {
        swap(arr[0], arr[i]);
        max_heapify(arr, 0, i - 1);
    }
}
int main() {
    int arr[] = { 3, 5, 3, 0, 8, 6, 1, 5, 8, 6, 2, 4, 9, 4, 7, 0, 1, 8, 9, 7, 3, 1, 2, 5, 9, 7, 4, 0, 2, 6 };
    int len = (int) sizeof(arr) / sizeof(*arr);
    heap_sort(arr, len);
    for (int i = 0; i < len; i++)
        cout << arr[i] << ' ';
    cout << endl;
    return 0;
}

🔥冒泡排序

描述

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数
  3. 针对所有的元素重复以上的步骤,除了最后一个
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较

代码

#include <iostream>
using namespace std;

template<typename T>
void bubbleSort(T array[], int len) {
    int i, j;
    for (i = 0; i < len; ++i) {
        for (j = 0; j < len - 1; ++j) {
            if (array[j] > array[j + 1]) {
                swap(array[j], array[j + 1]);
            }
        }
    }
}

int main() {
    int array_int[] = {11, 24, 8, 32, 5, 65, 27};
    int len = (int) sizeof(array_int) / sizeof(array_int[0]);
    int i = 0;

    bubbleSort(array_int, len);
    for (i = 0; i < len; ++i) {
        cout << array_int[i] << " ";
    }
    cout << endl;
    
    return 0;
}

选择排序

#include <iostream>
#include <vector>
using namespace std;

template<typename T>
void selection_sort(vector<T>& arr) {
    for (int i = 0; i < arr.size() - 1; i++) {
        int min = i;
        for (int j = i + 1; j < arr.size(); j++) {
            if (arr[j] < arr[min]) {
                min = j;
            }
        }
        wap(arr[i], arr[min]);
    }
}
 
int main()
{
    vector<int> arr = {12, 5, 9, 41, 25, 3, 22};
    selection_sort(arr);
    for(int i = 0; i < arr.size(); ++i) {
        cout << arr[i] << ' ';
    }
    cout << endl;
    return 0;
}

其他算法

希尔排序

#include <iostream>

template<typename T>
void shell_sort(T array[], int length) {
    int h = 1;
    while (h < length / 3) {
        h = 3 * h + 1;
    }
    while (h >= 1) {
        for (int i = h; i < length; i++) {
            for (int j = i; j >= h && array[j] < array[j - h]; j -= h) {
                std::swap(array[j], array[j - h]);
            }
        }
        h = h / 3;
    }
}
 
int main()
{
    int arr[] = {12, 5, 9, 41, 25, 3, 22};
    shell_sort(arr, 7);
    for(int i = 0; i < 7; ++i) {
        std::cout << arr[i] << ' ';
    }
    std::cout << std::endl;
    return 0;
}

插入排序

插入排序

计数排序

计数排序

桶排序

桶排序

基数排序

基数排序

参考资料

阿秀的求职笔记

排序算法之堆排序

《算法导论》

《数据结构 C++语言版》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值