常见排序算法(C++实现)

排序的稳定性
  • 排序后原本相同的值相对次序的保持不变。
  • 稳定:冒泡排序,插入排序,归并排序,桶排序
  • 不稳定:选择排序,快速排序(有稳定的版本),堆排序,希尔排序
冒泡排序
  • 平均时间复杂度:O(N^2)
  • 额外空间复杂度O(1)
  • 稳定
void bubbleSort(vector<int> &vec)
{
	if (vec.size() < 2) return;
	for (int i = vec.size() - 1; i > 0; i--) {
		for (int j = 0; j < i; j++) {
			if (vec[j] > vec[j + 1])
				vectorSwap(vec, j, j + 1);
		}
	}
}
选择排序
  • 平均时间复杂度:O(N^2)
  • 额外空间复杂度O(1)
  • 不稳定
void selectionSort(vector<int> &vec)
{
    if (vec.size() < 2) return;
    for (int i = vec.size() - 1; i > 0; i--) {
        int maxIndex = 0;
        for (int j = 1; j <= i; j++) {
            if (vec[maxIndex] < vec[j])
                maxIndex = j;
        }
        vectorSwap(vec, maxIndex, i);
    }
}
插入排序
  • 平均时间复杂度:O(N^2)
  • 最好:O(N) --> 1, 2, 3, 4, 5
  • 最差:O(N^2) --> 5, 4, 3, 2, 1
  • 额外空间复杂度O(1)
  • 稳定
void insertionSort(vector<int> &vec)
{
	if (vec.size() < 2) return;
	for (int i = 1; i < vec.size(); i++) {
		for (int j = i - 1; j >= 0 && vec[j] > vec[j + 1]; j--) {
			vectorSwap(vec, j, j + 1);
		}
	}
}
归并排序
  • 平均/最好/最坏 时间复杂度:O(NlogN)
  • 额外空间复杂度:O(N)
  • 稳定
void merge(vector<int> &vec, int left, int mid, int right)
{
	int len = right - left + 1;
	vector<int> tempVec(len);
	int i = 0, p1 = left, p2 = mid + 1;
	while (p1 <= mid && p2 <= right) {
		tempVec[i++] = vec[p1] <= vec[p2] ? vec[p1++] : vec[p2++];
	}
	while (p1 <= mid) {
		tempVec[i++] = vec[p1++];
	}
	while (p2 <= right) {
		tempVec[i++] = vec[p2++];
	}
	for (i = 0; i < len; i++) {
		vec[left + i] = tempVec[i];
	}
}

void sortProcess(vector<int> &vec, int left, int right)
{
	if (left == right) return;
	int mid = left + ((right - left) >> 1);
	sortProcess(vec, left, mid);
	sortProcess(vec, mid + 1, right);
	merge(vec, left, mid, right);
}

void mergeSort(vector<int> &vec)
{
	if (vec.size() < 2) return;
	sortProcess(vec, 0, vec.size() - 1);
}
快速排序
  • 平均/最好 时间复杂度:O(NlogN)
  • 最差情况时间复杂度退化到O(N^2) --> 划分值选取不好,每次选取的划分值不是最大就是最小,导致每次只排好一个数据。
  • 额外空间复杂度:O(logN)
  • 不稳定(有稳定的版本)
/** 无优化重复数据 */
int myPartition(vector<int> &arr, int left, int right)
{
    int small = left - 1;
    while (left < right) {
        if (arr[left] < arr[right])
            vectorSwap(arr, left++, ++small);
        else left++;
    }
    vectorSwap(arr, small + 1, right);
    return small + 1;
}

void quickSort(vector<int> &arr, int left, int right) {
    if (left < right) {
        int pivot = myPartition(arr, left, right);
        quickSort(arr, left, pivot - 1);
        quickSort(arr, pivot + 1, right);
    }
}

/** 对重复数据进行优化 */
/** 荷兰国旗问题:给定一个划分值,将数组划分为小于区,等于区,大于区
    小于区 | 等于区 | (当前判断位置)待定区 | 大于区 */
vector<int> myPartition(vector<int> &vec, int left, int right)
{

    int small = left - 1;
    int big = right;
    while (left < big) {
        if (vec[left] < vec[right]) vectorSwap(vec, ++small, left++);
        else if (vec[left] > vec[right]) vectorSwap(vec, --big, left);
        else left++;
    }
    vectorSwap(vec, big, right);
    vector<int> equalVec = {small + 1, big};
    return equalVec;
}

void quickSort(vector<int> &vec, int left, int right)
{
    if (left < right) {
        vectorSwap(vec, right, left + random(right - left + 1));
        vector<int> equalVec = myPartition(vec, left, right);
        quickSort(vec, left, equalVec[0] - 1);
        quickSort(vec, equalVec[1] + 1, right);
    }
}
堆排序
  • 平均/最好/最差 时间复杂度:O(NlogN)
  • 额外空间复杂度:O(1)
  • 不稳定
  • 堆:完全二叉树
  • 大/小根堆:所有子树(包括自身)最大/小值都在对应树的根节点。
  • 用数组表示完全二叉树:当前节点/数组下标 i --> 左孩子 i * 2 + 1,右孩子 i * 2 + 2,父节点 (i - 1) / 2
void heapInsert(vector<int> &vec, int index)
{
	while (vec[index] > vec[(index - 1) / 2]) {
		vectorSwap(vec, index, (index - 1) / 2);
		index = (index - 1) / 2;
	}
}

void heapify(vector<int> &vec, int index, int size)
{
	int left = index * 2 + 1;
	while (left < size) {
		int largest = (left + 1 < size) && (vec[left + 1] > vec[left]) ? left + 1 : left;
		largest = vec[largest] > vec[index] ? largest : index;
		if (largest == index) break;
		vectorSwap(vec, index, largest);
		index = largest;
		left = index * 2 + 1;
	}
}

void heapSort(vector<int> &vec)
{
	if (vec.size() < 2) return;
	for (int i = 1; i < vec.size(); i++) { //建大根堆
		heapInsert(vec, i);
	}
	int heapSize = vec.size();
	vectorSwap(vec, 0, --heapSize);
	while (heapSize > 1) {
		heapify(vec, 0, heapSize);
		vectorSwap(vec, 0, --heapSize);
	}
}
桶排序
  • 计数排序
  • 基数排序
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值