C_C++算法_排序算法

本文详细介绍了插入排序、选择排序、归并排序(自顶向下与自底向上)和快速排序(包括传统与三路快排)的实现思路及代码,并通过测试在完全无序、基本有序和大量重复数组上的运行时间,展示了各种排序算法的性能差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

插入排序

思路

遍历数组将当前位置的数据依次与前边的数据进行比较符合条件则进行交换。

代码

namespace AC {
    template <typename T>
    void insertionSort(T _target_array[], int _array_count) {
        for (int index = 1; index < _array_count; ++index) {
            T temp_data = _target_array[index];
            int move_index = index;
            for (; move_index > 0 && _target_array[move_index - 1] > temp_data; --move_index) {
                _target_array[move_index] = _target_array[move_index - 1];
            }
            _target_array[move_index] = temp_data;
        }
    }
}

选择排序

思路

数据分为两个部分已排序部分未排序部分在未排序部分的数据中找到最小或最大的数据,与未排序部分的第一个位置的数据进行交换。

代码

namespace AC {
    template <typename T>
    void selectionSort(T _target_array[], int _array_count) {
        for (int index = 0; index < _array_count - 1; ++index) {
            int min_index = index;
            for (int comp_index = index + 1; comp_index < _array_count; ++comp_index) {
                if(_target_array[min_index] > _target_array[comp_index]) {
                    min_index = comp_index;
                }
            }
            std::swap(_target_array[index], _target_array[min_index]);
        }
    }
}

归并排序-自顶向下

思路

将未排序的数组划分为多个小的数组段,将每个小的数组段进行排序,然后将每个排序好的数组段进行合并汇总,最终汇总成一个有序的数组。

代码

namespace AC {
	template <typename T>
	void mergeSort(T _target_array[], int _array_count) {
        __mergeSort(_target_array, 0, _array_count - 1);
    }
    
    template <typename T>
    void __mergeSort(T _target_array[], int _left, int _right) {
        if (_left >= _right) {
            return;
        }
        int mid = (_left + _right) / 2;
        __mergeSort(_target_array, _left, mid);
        __mergeSort(_target_array, mid + 1, _right);
        // 如果左半部分的最后一个数值大于右半部分第一个数值则再进行合并,否则说明两个部分的数据已经有序不用再次合并
        if (_target_array[mid] > _target_array[mid + 1]) {
			__merge(_target_array, _left, mid, _right);
    	}
    }

    template <typename T>
    void __merge(T _target_array[], int _left, int _mid, int _right) {
        T * aux = new int[_right - _left + 1];
        for (int index = _left; index <= _right; ++index) {
            aux[index - _left] = _target_array[index];
        }

        int i = _left, j = _mid + 1;
        for (int k = _left; k <= _right; ++k) {
            if (i > _mid) {
                _target_array[k] = aux[j - _left];
                j++;
            } else if (j > _right) {
                _target_array[k] = aux[i - _left];
                i++;
            } else if (aux[i - _left] < aux[j - _left]) {
                _target_array[k] = aux[i - _left];
                i++;
            } else {
                _target_array[k] = aux[j - _left];
                j++;
            }
        }

        delete [] aux;
    }
}

归并排序-自底向上

思路

先将数组从左头到尾依次划分为多个小段,一般从两个元素一段开始进行归并,当归并完成一轮(到末尾后)后,在成倍扩展一下分段,再次从头到尾进行归并,直至扩展结束。

代码

namespace AC {
    template <typename T>
	void mergeSortBU(T _target_array[], int _array_count) {
        for (int index = 1; index <= _array_count; index += index) {
            for (int i = 0; i + index < _array_count; i += index + index) {
                __merge(_target_array, i, i + index - 1, std::min(i + index + index - 1, _array_count - 1));
            }
        }
    }
}

快速排序

思路

首先找到一个数作为基础数值,以基础数值作为中点将数据分为前后两个部分,前半部分全部小于基础数值而后半部分全部大于基础数值,然后分别在前后两个部分中找到新的基础数值重复进行以上步骤。

代码

namespace AC {
    template <typename T>
    void quickSort(T _target_array[], int _array_count) {
        srand(time(nullptr)); // 设置随机数优化当数值大量有序的时候分段偏不均
        __quickSort(_target_array, 0, _array_count - 1);
    }
    
    template <typename T>
    int __partition(T _target_array[], int _left, int _right) {
        // 将最左边的数和后边随机位置的一个数据交换,可以优化当数组数据基本有序时快速排序退化为O(n^2)级别的算法
        std::swap(_target_array[_left], _target_array[rand() % (_right - _left + 1) + _left]);
        T aux = _target_array[_left]; 
        int j = _left;
        for (int i = _left + 1; i <= _right; ++i) {
            if (_target_array[i] < aux) {
                std::swap(_target_array[++j], _target_array[i]);
            }
        }
        std::swap(_target_array[_left], _target_array[j]);
        return j;
    }

    template <typename T>
    void __quickSort(T _target_array[], int _left, int _right) {
        if (_left >= _right) {
            return;
        }
        // 快速排序定位基础数值是算法核心
        int partition_index = __partition(_target_array, _left, _right);
        __quickSort(_target_array, _left, partition_index - 1);
        __quickSort(_target_array, partition_index + 1, _right);
    }
}

快速排序- 三路排序

思路

按照基础数值V将数组分为三个部分,小于V、大于V和等于V,定义ltgtindex三个变量,lt是小于V部分的最后一个数值所在位置,gt是大于V部分的第一个数值所在位置,等于V部分的区域范围是[lt + 1...index - 1]index是未排序部分的第一个数值所在位置。

index的数值小于V时与lt + 1进行交换;当index的数值大于V时与gt - 1进行交换;当index的数值等于V时继续下一次比较。

代码

namespace AC {
    template <typename T>
    void quickSort(T _target_array[], int _array_count) {
        srand(time(nullptr)); // 设置随机数优化当数值大量有序的时候分段偏不均
        __quickSort3Ways(_target_array, 0, _array_count - 1);
    }
    
    template <typename T>
    void __quickSort3Ways(T _target_array[], int _left, int _right) {
        if (_right <= _left) {
            return;
        }
        std::swap(_target_array[_left], _target_array[rand() % (_right - _left + 1) + _left]);
        T aux = _target_array[_left];
        int lt = _left, gt = _right + 1, index = _left + 1;
        while (index < gt) {
            if (_target_array[index] < aux) {
                std::swap(_target_array[index++], _target_array[++lt]);
            } else if (_target_array[index] > aux) {
                std::swap(_target_array[index], _target_array[--gt]);
            } else {
                ++index;
            }
        }
        std::swap(_target_array[_left], _target_array[lt]);
        __quickSort3Ways(_target_array, _left, lt - 1);
        __quickSort3Ways(_target_array, gt, _right);
    }
}

测试

完全无序

  • 代码
#include <iostream>

#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"

int main() {
    int array_count = 50000;
	// 生成随机数组
    int * arrays = SortTestHelper::generateRandomArray(array_count, 1, array_count);
	// 5种排序算法
    return 0;
}

  • 结果
insertionSort: 1.234 s.
selectionSort: 2.357 s.
mergeSort: 0.016 s.
mergeSortBU: 0.019 s.
quickSort: 0.011 s.
quickSort3Ways: 0.013 s.

基本有序

  • 代码
#include <iostream>

#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"

int main() {
    int array_count = 50000;
	// 生辰一个有序的数组,随机将其中的10个位置进行调换
    int * arrays = SortTestHelper::generateNearlyOrderedArray(array_count, 10);
    // 5种排序算法
    return 0;
}

  • 结果
insertionSort: 0.001 s.
selectionSort: 2.369 s.
mergeSort: 0.001 s.
mergeSortBU: 0.016 s.
quickSort: 0.009 s.
quickSort3Ways: 0.014 s.

无序大量重复数组

  • 代码
#include <iostream>

#include "src/sort_test_helper.cpp"
#include "src/sort_algoritm.cpp"

int main() {
    int array_count = 50000;
	// 生成一个无序的数组,其中的值在1-10之间
    int * arrays = SortTestHelper::generateRandomArray(array_count, 1, 10);
	// 5种排序算法
    return 0;
}

  • 结果
insertionSort: 1.1 s.
selectionSort: 2.35 s.
mergeSort: 0.013 s.
mergeSortBU: 0.017 s.
quickSort: 0.255 s.
quickSort3Ways: 0.001 s.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值