排序算法 | 插入快速希尔等

在这里插入图片描述

直接插入排序:

  • 最坏时间复杂度 O(n^2)
  • 平均时间复杂度 O(n^2/4)
  • 空间复杂度 O(1)
  • 稳定
  • 改进:折半插入(因为折半查找比顺序查找性能好,可以减少比较次数,但移动次数没有减少)
    2路插入、希尔排序…
  • 每次要处理的元素的左边都是有序序列

希尔排序:

  • 时间复杂度O(n^1.25) 与所取的增量序列有关。
  • 空间复杂度 O(1)
  • 要求:各增量互素,且最小增量为1;顺序存储
  • 不稳定

冒泡排序:

  • 时间复杂度 O(n^2)
  • 平均时间复杂度 O(n^2/2)
  • 空间复杂度 O(1)
  • 稳定
  • 缺点:没有利用已排序的结果
  • 注意:不要忘了设置flag(一趟排序没有交换表示已经排好序)

堆排序:

  • 时间复杂度 O(nlogn)
  • 空间复杂度 O(1)
  • 不稳定
  • 适用于 n 较大的情况
  • 注意:若从小到大排序,则设置小顶堆(每个结点的值都比左右结点的值小),每次取根结点,并更新最小堆。

快速排序:

  • 思想:分治策略
  • 最坏时间复杂度:O(n^2)
  • 平均、最好时间复杂度:O(nlogn) (内排序中最好的)
    空间复杂度:O(logn)~O(n) (递归用栈,二叉树的高度)
  • 不稳定
  • 最适合:数据完全无序,数据量大

基数排序:

  • 思想:桶排序。
  • 特点:非比较、多关键字
  • 对于一位数的整数进行排序的时间复杂度是O(n),非常适合对一位数的整数进行排序

桶排序

  • 将元素根据规则分组,每一组采用快排、插入排序等算法进行排序,然后再按照次序将所有元素合并,就可以得到一个有序序列
#include <iostream>
#include <stdlib.h>
using namespace std;

//直接插入排序
void insert_sort(int arr[], int n)
{
    int temp;
    // 左边无序,右边有序
    for (int i = 1; i < n; i++)
    {
        //可以冒泡也可以这样后移,这样看起来好点,赋值操作少。
        temp = arr[i];
        int k = i - 1;
        for (; k >= 0; k--)
        {
            if (arr[k] > temp)
            {
                arr[k + 1] = arr[k];
            }
            else
                break;
        }
        arr[k + 1] = temp;
    }
}

//希尔排序
void shell_sort(int arr[], int n)
{
    int d = n / 2;
    while (d > 0)
    {
        //组内“直接插入排序”
        int temp;
        for (int i = d; i < n; i += d)
        {
            temp = arr[i];
            int k = i - 1;
            for (; k >= 0; k--)
            {
                if (arr[k] > temp)
                {
                    arr[k + 1] = arr[k];
                }
                else
                    break;
            }
            arr[k + 1] = temp;
        }
        d /= 2;
    }
}

//冒泡排序
void bubble_sort(int arr[], int n)
{
    int temp;
    n--;
    bool flag = true;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n - i; j++)
        {
            if (arr[j] > arr[j + 1])
            {
                temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = false;
            }
        }
        
        if (flag)
            break;
        flag = true;
    }
}

//堆排序
void heapfy(int arr[], int node, int n)
{
    if (node > n / 2 || node < 0)
        return;

    int lChild = node * 2 + 1;
    int rChild = node * 2 + 2;
    int min = arr[node];

    //小顶堆.找孩子结点的最小值
    if (rChild < n && min > arr[rChild])
        min = arr[rChild];
    if (lChild < n && min > arr[lChild])
        min = arr[lChild];

    //若孩子结点最小值比该结点小,则交换值.交换后要检测孩子结点还对吗
    if (min != arr[node])
    {
        if (rChild < n && min == arr[rChild])
        {
            arr[rChild] = arr[node];
            heapfy(arr, rChild, n);
        }
        else if (lChild < n && min == arr[lChild])
        {
            arr[lChild] = arr[node];
            heapfy(arr, lChild, n);
        }
        arr[node] = min;
    }
}

void heap_sort(int arr[], int n)
{
    for (int i = n; i > 0; i--)
    {
        for (int k = i / 2; k >= 0; k--)
        {
            heapfy(arr, k, i);
        }
        printf("%d ", arr[0]);
        arr[0] = arr[i - 1];
    }
}

// 快速排序
int partition(int arr[], int low, int high)
{
    // 要寻找arr[high]真正的位置(下标)
    int index = high;
    int base = arr[high];
    while (low < high)
    {
        while (arr[low] <= base && low < high)
            low++;
        while (arr[high] >= base && low < high)
            high--;
        if (low < high)
        {
            int temp = arr[low];
            arr[low] = arr[high];
            arr[high] = temp;
        }
    }

    if (index != low)
    {
        arr[index] = arr[low];
        arr[low] = base;
    }
    return low;
}

void quick_sort(int arr[], int low, int high)
{
    int position; //目标数应该在的位置下标
    if (low < high)
    {
        position = partition(arr, low, high);
        quick_sort(arr, low, position - 1);
        quick_sort(arr, position + 1, high);
    }
}

// 检验数组是否是从小到大排列的
bool is_order(int arr[], int n)
{
    for (int i = 0; i < n - 1; i++)
    {
        if (arr[i] > arr[i + 1])
            return false;
    }
    return true;
}

int main()
{
    int n;
    scanf("%d", &n);
    int arr[n];
    for (int i = 0; i < n; i++)
    {
        arr[i] = int(rand());
    }
    
    shell_sort(arr, n);
    
    for (int i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值