基本的排序算法

基本的排序算法

  • 选择排序
  • 冒泡排序
  • 插入排序
  • 快速排序
  • 合并排序
  • 基数排序
  • 堆排序

选择排序

算法思路:假设A[1…n]是一个有n个元素的数组。

  1. 首先从A[1…n]找到最小元素,将其放在A[1]中
  2. 从A[2…n]中找到最小元素,将其放在A[2]中
  3. 重复A[i…n]中找到最小元素,将其放在A[i]中
  4. 直至i=n-1

元素比较次数: ni=1(ni)=ni=1i=n(n1)/2

时间复杂度为 O(n2)
不稳定排序

代码实现:

void selectionSort(int arr[], int len)
{
    int k, temp;;
    for (int i = 0; i < len-1; i++)
    {
        k = i;
        for (int j = i + 1; j < len; j++)
        {
            if (arr[j] < arr[k])
                k = j;
        }
        if (k != i)
        {
            temp = arr[k];
            arr[k] = arr[i];
            arr[i] = temp;
        }
    }
}

冒泡排序

算法思路:假设A[1…n]是一个有n个元素的数组。

  1. 从A[n]向前遍历直至A[ 1 ],如果A[j]小于A[j-1],A[j]与A[j-1]交换,依次遍历,A[1]为最小元素
  2. 从A[n]向前遍历直至A[ 2 ],类似1
  3. 直到所有元素都以非降序排列,或前n-1个元素都已排序

元素比较次数: ni=1(ni)=ni=1i=n(n1)/2

时间复杂度为 O(n2)
稳定排序

代码实现:

void bubbleSort(int arr[], int len)
{
    bool flag = true;
    int i, j, temp;
    for (i = 0; i < len - 1; i++)
    {
        for (j = len - 1; j>i; j--)
        {
            if (arr[j] < arr[j - 1])
            {
                flag = false;
                temp = arr[j];
                arr[j] = arr[j - 1];
                arr[j - 1] = temp;
            }
        }
        if (flag)  //如果所有元素均已有序,直接跳出循环
            break;
    }
}

插入排序

算法思路:假设A[1…n]是一个有n个元素的数组

  1. 从大小为1的子数组A[ 1 ]开始,将A[ 2 ]插入到A[ 1 ]的前面或后面,完成一次排序。
  2. 重复以下过程:将A[i]插入到已排序的子数组A[1…i-1]中合适位置。
  3. 直至i=n

元素比较次数: ni=2(i1)=n1i=1i=n(n1)/2

时间复杂度为 O(n2)
稳定排序

代码实现:

void insertSort(int arr[], int len)
{
    int i, j, temp;
    for (i = 1; i < len; i++)
    {
        temp = arr[i];
        j = i - 1;
        while (j >= 0 && arr[j]>temp)  //循环遍历arr[0...i-1],将arr[i]插入合适位置
        {
            arr[j + 1] = arr[j];
            j--;
        }
        arr[j + 1] = temp;
    }
}

快速排序

算法思路:

  1. 先从数列中取出一个数作为基准数。
  2. 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
  3. 再对左右区间重复第二步,直到各区间只有一个数。

平均时间复杂度为 O(nlog2n) ,最坏时间复杂度为 O(n2)
不稳定排序

代码实现:

void quickSort(int arr[], int low, int high)
{
    if (low < high)
    {
        int mid, l, r, temp;
        l = low, r = high;
        temp = arr[high];
        while (l < r)
        {
            while (l<r&&arr[l] <= temp)
                l++;
            if (l < r)
                arr[r] = arr[l];
            while (l<r&&arr[r] >= temp)
                r--;
            if (l < r)
                arr[l] = arr[r];
        }
        arr[l] = temp;
        mid = l;
        quickSort(arr, low, mid - 1);
        quickSort(arr, mid + 1, high);
    }
}

合并排序

算法思路:自顶向下,不断将数组分成两半,直至每部分只有一个元素。再合并两部分已排好序的的数组成为一个数组。

平均时间复杂度为 O(nlog2n)
稳定排序

代码实现:

void Merge(int arr[], int low, int mid, int high)
{
    int len = high - low + 1;
    int *copy = new int[len];
    int i = low, j = mid + 1, k = low;
    while (i <= mid&&j <= high)
    {
        if (arr[i] <= arr[j])
            copy[k - low] = arr[i++];
        else
            copy[k - low] = arr[j++];
        k++;
    }
    if (i == mid + 1)
    {
        for (int ii = j; ii <= high; ii++)
        {
            copy[k - low] = arr[ii];
            k++;
        }
    }
    else
    {
        for (int ii = i; ii <= mid; ii++)
        {
            copy[k - low] = arr[ii];
            k++;
        }
    }
    for (i = low; i <= high; i++)
    {
        arr[i] = copy[i - low]; 
    }
}
void mergeSort(int arr[], int low, int high)
{
    if (low < high)
    {
        int mid = floor((low + high) / 2);
        mergeSort(arr, low, mid);
        mergeSort(arr, mid + 1, high);
        Merge(arr, low, mid, high);
    }
}

堆排序

创建堆:时间复杂度为 O(n)
堆排序:平均时间复杂度为 O(nlog2n) O(n) ,siftdown O(log2n) 时间,重复n-1次】

不稳定排序

代码实现:

void SiftDown(int arr[], int len, int idx)
{
    bool done = false;
    int par, temp;
    if (idx * 2 >= len)
        return;
    while (2 * idx < len && done==false)
    {
        par = idx;
        idx = 2 * idx;
        if (idx + 1 < len&&arr[idx + 1] > arr[idx])  //对比左右子结点,找较大值
            idx = idx + 1;
        if (arr[par] < arr[idx])
        {
            temp = arr[idx];
            arr[idx] = arr[par];
            arr[par] = temp;
        }
        else
            done = true;
    }
}

void makeHeap(int arr[], int len)
{
    int k = floor((len - 1) / 2);
    for (int i = k; i >= 0; i--)
    {
        SiftDown(arr, len, i);
    }
}

void heapSort(int arr[], int len)
{
    makeHeap(arr, len);
    for (int i = 0; i<len; i++)
        cout << arr[i] << " ";
    cout << endl;
    for (int i = len - 1; i > 0; i--)
    {
        int temp = arr[i];
        arr[i] = arr[0];
        arr[0] = temp;
        SiftDown(arr, --len, 0);
    }
}

基数排序

算法思路:假设L={a1,a2,a3…an}是一个有n个元素的表,其中每个元素恰好有k位数字,即 dkdk1...d1 di 是0-9的数字。

  1. 首先根据 d1 位,把表中所有元素分到 L0L1...L9 中,即 d1=0 的数分到 L0 中, d1=1 的数分到 L1 中,等等。
  2. 按照 d2 分到10张表中,按顺序连接起来。
  3. 依次进行到 dk ,即可完成排序。

时间复杂度为 O(kn)
稳定排序

举例:下面为8个四位数

初始第 一次第二次第三次第四次
7467679 293 1 49 1 341 239
1247913 412 3 99 1 871 247
3275327 512 4 71 2 393 275
6792467 574 6 71 2 474 675
9187746 732 7 53 2 756 792
9134124 746 7 57 4 677 467
4675918 791 8 74 6 759 134
1239123 967 9 26 7 929 187
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值