zoukankan      html  css  js  c++  java
  • 排序算法

    #include <iostream>
    #define MAXSIZE 10
    typedef struct  
    {
        int r[MAXSIZE + 1];//用于存储排序的数组,r[0]用作哨兵或临时变量
        int length;           //用于记录顺序表的长度
    }SqlList;
    
    void swap(SqlList* L, int i, int j)
    {
        int temp = L->r[i];
        L->r[i] = L->r[j];
        L->r[j] = temp;
    }
    /*
    基本思想:从头开始将每个元素与后面的每个元素比较,将较小的放在当前位置,这样下来就将最小的元素放在了当前位置
    但前面排好的对后面的没有作用,也许较小的放到后面了
    */
    void BubbleSort0(SqlList* L)
    {
        int i, j;
        for (i = 1; i < L->length; ++i)
        {
            for (j = i + 1; j <= L->length; ++j)
            {
                if (L->r[i] > L->r[j])
                {
                    swap(L, i, j);    //交换i和j对应元素的值
                }
            }
        }
    }
    
    //从后往前比较
    void BubbleSort(SqlList* L)
    {
        int i, j;
        for (i = 1; i < L->length; ++i)
        {
            for (j = L->length - 1; j >= i; j--)
            {
                if (L->r[j] > L->r[j + 1])
                {
                    swap(L, j, j + 1);
                }
            }
        }
    }
    
    
    //从前往后比较
    void BubbleSort1(SqlList* L)
    {
        int i, j;
        bool bFalg = true;//如果一次比较没变动直接退出循环,提高效率
        for (i = 1; i < L->length && bFalg; ++i)
        {
            bFalg = false;
            for (j = 1; j <= L->length - i; ++j)
            {
                if (L->r[j] > L->r[j + 1])
                {
                    swap(L, j, j + 1);
                    bFalg = true;
                }
            }
        }
    }
    
    
    /*
    选择排序,从前往后记录最小位置,然后找出后面最小的然后和当前位置交换,这个是比较次数较多,外层for只进行一次比较
    */
    void SelectSort(SqlList* L)                
    {
        int i, j, min;
        for (i = 1; i < L->length; ++i)
        {
            min = i;
            for (j = i + 1; j <= L->length; ++j)
            {
                if (L->r[min] > L->r[j])
                {
                    min = j;
                }
            }
        }
        if (i != min)
        {
            swap(L, i, min);
        }
    }
    
    /*
    基本思想:先假定前面排好序,然后将要排序的插入到前面有序的数组中
    o(n2)性能比冒泡和简单选择排序性能要好
    */
    void InsertSort(SqlList* L)
    {
        for (int i = 2; i < L->length; ++i)
        {
            L->r[0] = L->r[i];//当前元素存储在哨兵中
            int j;
            for (j = i - 1; j >= 1; --j)
            {
                if (L->r[j] > L->r[0])
                {
                    L->r[j + 1] = L->r[j];
                }
                else
                {
                    break;
                }
            }
            L->r[j + 1] = L->r[0];
        }
    }
    
    int Partition(SqlList* L, int low, int high)
    {
        int val = L->r[low];// 存放要分割的值
        while (low < high && L->r[high] > L->r[low])//先进行high移动,只要比分割值大就左移
            high--;
        swap(L, low, high);//对应的值小于分割值,则进行替换l对应值
        while (low < high && L->r[low] < L->r[high])//进行low移动,比分割之小右移
            low++;
        swap(L, low, high);//如果大于分割值替换h对应值
        return low;
    }
    
    void QSort(SqlList* L, int low, int high)
    {
        int pivot;
        if (low < high)
        {
            pivot = Partition(L, low ,high);
            //左右部分的排序
            QSort(L, low, pivot - 1);
            QSort(L, pivot + 1, high);
        }
    }
    
    /*
    先选择轴值,左右指针,如果右边的索引比轴值小往做移动,然后比较左边,如果左边的索引比轴值大往右移动,当左索引和右索引相等时该位置就是轴值呆的地方
    然后再比较轴值左边的,在比较轴值右边的
    通过一趟将待排序的记录,将记录分割成两部分,一部分比另一部分小,接下来再进行左右两部分记录的排序
    */
    void QuickSort(SqlList* L)
    {
        QSort(L, 1, L->length);
    }
    
    /*
    基本思想:每次按照跨度排序,然后这个跨度不断的减小,每次排序内部是插入排序
    插入排序对于基本有序和较短的序列有较高的效率,时间复杂度为n1.5次方
    并且这个跨度有限制的,例如除以二递减还是n2方的
    */
    void ShellSort(SqlList* L)
    {
        int i, j;
        int increment = L->length;
        do 
        {
            increment = increment / 3 + 1;//增量选择
            for (i = increment + 1; i <= L->length; i++)
            {
                if (L->r[i] < L->r[i - increment])//内部就是根绝增量的插入排序
                {
                    L->r[0] = L->r[i];
                    for (j = i - increment; j > 0 && L->r[0] < L->r[j]; j -= increment)
                    {
                        L->r[j + increment] = L->r[j];
                    }
                    L->r[j + increment] = L->r[0];
                }
            }
        } 
        while (increment > 1);
    }
    
    void MSort(int SR[], int TR1[], int s, int t)
    {
        int m;
        int TR2[MAXSIZE + 1];
        if (s == t)
        {
            TR1[s] = SR[s];
        }
        else
        {
            s = (s + t) / 2;
            MSort(SR, TR2, s, m);
            MSort(SR, TR2, m + 1, t);
            //Merge(TR2, TR1, s, m, t);未实现看大话
        }
    }
    
    
    /*
    看这个归并排序很复杂,程序更是复杂,能写出来的也是牛B
                    3 4 21 45 52 134 4 67 45 34
                  3 4 21 45 52      134 4 67 45 34
                3 4 21  45 52      134 4 67  45 34
            3 4  21    45  52   134 4   67   45  34
            3 4 21    45 52    4 134      34 45 67
            3 4 21 45 52            4 34 45 67 134
              3 4 4 21 34 45 45 52 67 134
        其大体思想就是先进行对半分割,然后再两两合并排序一直到所有的都排序了
    */
    void MergeSort(SqlList* L)
    {
        MSort(L->r, L->r, 1, L->length);
    }
    
    /*
    堆排序(理解思路就行了,写就算了)
    先将待排序的数字建成最小值堆,建立最小值堆的速度还是挺快的
    堆:分为大根堆和小根堆,属于完全二叉树(完全二叉树可以用数组存储)
    加入要从小排序,就每次从根节点取,最从小排序了
    */
    
    /*
    优先队列:好像是二叉树实现的
    散列表(哈希表):用哈希函数计算存储数据的地址
    */
    int main()
    {
        SqlList qList;
        int num[MAXSIZE] = {9, 1, 5, 8, 3, 7, 4, 6, 2, 10};
        memcpy(&qList.r[1], &num[0], MAXSIZE * sizeof(int));
        qList.length = MAXSIZE;
    
        //BubbleSort0(&qList);
        //BubbleSort(&qList);
        //BubbleSort1(&qList);
        //InsertSort(&qList);
        //QuickSort(&qList);
        ShellSort(&qList);
        for (auto j : qList.r)
        {
            std::cout << j << " ";
        }
        getchar();
        return 0;
    }
  • 相关阅读:
    HashMap的负载因子为什么默认是0.75?这篇文章告诉你答案
    如何设计短网址系统?
    前端HTML史上最全总结,入门级边学边实战!
    阿里2021最全新的java面试题总结
    三万字,100题!Linux知识汇总!
    程序员路线图
    基于nodejs的selenium的自动化测试之网络元素
    Electron桌面程序入门研究
    Git常用命令
    二次探测法
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/4372988.html
Copyright © 2011-2022 走看看