zoukankan      html  css  js  c++  java
  • 数据结构-快速排序

    1、快速排序(最好的内排序)

    1)在待排序的元素任取一个元素作为基准(通常选第一个元素,但最好的选择方法是从待排序元素中随机选取一个作为基准),称为基准元素;
    2)将待排序的元素进行分区,比基准元素大的元素放在它的右边,比其小的放在它的左边;
    3)对左右两个分区重复以上步骤直到所有元素都是有序的。

    #include <stdio.h>
    #include <stdlib.h>
    
    void swap(int k[], int low, int high)
    {
        int temp = k[low];
        k[low] = k[high];
        k[high] = temp;
    }
    
    //交换顺序表中子表顺序,返回枢纽所在的位置,此时在枢纽之前(不大于)后(不小于)
    int Partition(int k[], int low, int high)
    {
        int pivotkey;
        pivotkey = k[low]; //枢纽选取为第一个元素
        while (low < high)
        {
            while (low < high && k[high] >= pivotkey)//将右侧比枢纽小的值,调整至低端
                high--;
            swap(k, low, high);
            while (low < high && k[low] <= pivotkey)//将左侧比枢纽大的值,调整至高端
                low++;
            swap(k, low, high);
        }
        return low;//此时low=high,返回枢纽所在位置
    }
    
    void QuickSort(int k[], int low, int high)
    {
        int pivot;
        if (low < high)
        {
            pivot = Partition(k, low, high);
            QuickSort(k, low, pivot - 1);   //对枢纽左侧递归排序
            QuickSort(k, pivot + 1, high);  //对枢纽右侧递归排序
        }
    }
    
    int main()
    {
        int i;
        int a[10] = { 5, 2, 6, 0, 3, 9, 1, 7, 4, 8 };
        QuickSort(a, 0, 9);
    
        for (i = 0; i < 10; i++)
            printf_s("%d ", a[i]);
    
        return 1;
    }

    改进1:三数取中,取三个关键字先解析排序,将中间数作为枢轴,一般取左端,右端和中间三个数

    如果我们选取的枢轴值正好是处于整个序列大小的中间位置,那么可以将序列分为小数集合和大数集合。但是若是我们第一个选取的是最大值呢?我们交换后实质变化并不大

    int Partition(int k[], int low, int high)
    {
        int pivotkey;
        int m = low + (high - low) / 2;
        //三数取中的判断
        if (k[low] > k[high])
            swap(k, low, high);
        if (k[m] > k[high])
            swap(k, m, high);
        if (k[m] < k[low])
            swap(k, m, low);
        //此时m处是三个数中间值
    
        pivotkey = k[m];    //用子表第一个记录左枢轴记录
        while (low < high)    //从表的两端交替向中间扫描
        {
            while (low < high && k[high] >= pivotkey)
                high--;
            swap(k, high, low);    //将比枢轴记录小的记录交换到低端
            while (low < high && k[low] <= pivotkey)
                low++;
            swap(k, low, high);    //将比枢轴记录大的记录交换到高端
        }
        return low;    //返回枢轴所在位置
    }

    改进二、优化小数组:当数组非常小时,使用快排还不如直接插入的性能好,二这个数组大小的阈值我们一般选取7最好

    #define MAX_LENGTH_INSERT_SORT 7    //数组阈值大小
    
    void InsertSort(int k[], int n)    //对数组部分进行快排
    {
        int i, j, temp;
        for (i = 1; i < n;i++)
        {
            if (k[i]<k[i-1])
            {
                temp = k[i];
                for (j = i - 1; k[j] > temp; j--)
                    k[j + 1] = k[j];
                k[j + 1] = temp;
            }
        }
    }
    
    void Qsort(int k[], int low, int high)
    {
        int pivot;
        if ((high-low)>MAX_LENGTH_INSERT_SORT)    //条件是包含high>low
        {
            pivot = Partition(k, low, high);
            Qsort(k, low, pivot - 1);    //对低子表进行递归排序
            Qsort(k, pivot + 1, high);    //对高子表进行递归排序
        }
        else
        {
            InsertSort(k + low, high - low + 1);    //对数组部分进行快排
        }
    }
  • 相关阅读:
    ORACLE不常用但实用的技巧- 树查询 level用法
    oracle的start with connect by prior如何使用
    Oracle SQL日期及日期格式获取命令
    2019年起一般纳税人和小规模纳税人的区别
    10.pandas的替换和部分替换(replace)
    pandas中.value_counts()的用法
    Python模块/包/库安装几种方法(转载)
    预处理数据的方法总结(使用sklearn-preprocessing)
    python时间序列分析之_用pandas中的rolling函数计算时间窗口数据
    BZOJ2007 [Noi2010]海拔
  • 原文地址:https://www.cnblogs.com/lemonzhang/p/12423512.html
Copyright © 2011-2022 走看看