几种常见排序算法

几种常见排序算法

使用语言及编译环境

  1. 使用语言:C/C++
  2. 编译环境:VS Code

冒泡排序

参照https://www.bilibili.com/video/BV1T4411A7Fy?p=7

  1. 原理:数组元素两两比较,交换元素,大元素往后放
    #include <iostream>
    
     using namespace std;
    
     int main()
     {
         int arrayLength = 6;
         int array[arrayLength] = {10,2,5,80,35,60};
    
         for (int i = 0; i < arrayLength; i++)
         {
             cout << array[i] << " ";
         }
         cout << endl;
    
         for (size_t i = 0; i < arrayLength-1; i++)
         {
             for (size_t j = 0; j < arrayLength-1-i; j++)
             {
                 if (array[j] > array[j+1])
                 {
                     int temp = array[j+1];
                     array[j+1] = array[j];
                     array[j] = temp;
                 }
    
             }
         }
    
         for (int i = 0; i < arrayLength; i++)
         {
             cout << array[i] << " ";
         }
         cout << endl;
    
         system("pause");
         return 0;
     }
    

选择排序

参照https://www.bilibili.com/video/BV1T4411A7Fy?p=8

  1. 原理:从0索引处开始,将该位置的元素依次和后面的元素进行比较,小的元素往前放
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        for (size_t index = 0; index < arrayLength-1; index++)
        {
            for (size_t i = index+1; i < arrayLength; i++)
            {
                if (array[index] > array[i])
                {
                    int temp = array[index];
                    array[index] = array[i];
                    array[i] = temp;
                } 
            } 
        }
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        system("pause");
        return 0;
    }
    

直接插入排序

参照https://www.bilibili.com/video/BV1T4411A7Fy?p=9

  1. 原理:从1索引处开始,将后面的元素插入之前的有序列表中,使之仍保持有序
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        for (size_t i = 1; i < arrayLength; i++)
        {
            for (size_t j = i; j > 0; j--)
            {
                if (array[j] < array[j-1])
                {
                    int temp = array[j];
                    array[j] = array[j-1];
                    array[j-1] = temp;
                }    
            }   
        }
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        system("pause");
        return 0;
    }
    

希尔排序

参照https://www.bilibili.com/video/BV1T4411A7Fy?p=10

  1. 原理:合理选取增量,一轮排序后,不断缩小增量进行插入排序,直到增量为1,排序就结束
  2. 直接插入排序相当于增量为1的希尔排序
  3. 增量的合理选择:克努特(Knuth)序列导入,h=3*h+1
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        //克努特序列选取增量
        int spac = 1;
        while (spac <= arrayLength/3)
        {
            spac = spac*3+1;
        } 
        //cout << "spac: " << spac << endl;
    
        for (size_t h = spac; h > 0; h=(h-1)/3)
        {
            for (size_t i = h; i < arrayLength; i++)
            {
                for (size_t j = i; j > h-1; j-=h)
                {
                    if (array[j] < array[j-h])
                    {
                        int temp = array[j];
                        array[j] = array[j-h];
                        array[j-h] = temp;
                    }    
                }   
            }
        }   
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        system("pause");
        return 0;
    }
    

快速排序

参照https://www.bilibili.com/video/BV1at411T75o/?spm_id_from=333.788

  1. 思想:分治法,比大小,在分区
  2. 原理:从数组中取一个数,将比这个数大的全放到右边,比这个数小的全放到左边;对左右两个分区进行此步骤,直到最后分区只有一个数
  3. 步骤:选一个基准数,先从后往前找小于它的数,将这个数放到基准数的位置,然后在从前往后找大于等于它的数,将这个数放到上一个小于基准数的位置,直到左右两个寻找的指针重合,然后重复对左区和右区进行上述操作,直到分区只有一个元素的时候,就认为整个数组有序了
    #include <iostream>
    
    using namespace std;
    
    void quickSort(int *arr, int start, int end);
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        quickSort(array, 0, arrayLength-1);
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        system("pause");
        return 0;
    }
    
    void quickSort(int *arr, int start, int end)
    {
        if (start>=end)
        {
            return;
        }
    
        int L = start;
        int R = end;
        int pivot = arr[L];
    
        while (L<R)
        {
            //由后往前找比它小的数
            while (L<R && arr[R]>=pivot)
            {
                R--;
            }
            if (L<R)
            {
                arr[L] = arr[R];
                L++;
            }
    
            //由前往后找比它大或者等于的数
            while (L<R && arr[L]<pivot)
            {
                L++;
            }
            if (L<R)
            {
                arr[R] = arr[L];
                R--;
            }
    
            //把基准数放到最后L和R重合的地方
            if (L>=R)
            {
                arr[L] = pivot;
            }   
        }
    
        //递归处理左区和右区
        quickSort(arr, start, L-1);
        quickSort(arr, L+1, end);
    }
    

归并排序

参照:https://www.bilibili.com/video/BV1Pt4y197VZ?spm_id_from=333.337.search-card.all.click

  1. 思想:先划分再合并
  2. 原理:将数组中每个元素分为一组,然后两两组合,保证每次组合出来的数组都是有序的,直到只剩下一组的时候,排序完成
    #include <iostream>
    
    using namespace std;
    
    void mergeSort(int *arr, int size);
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        mergeSort(array, arrayLength);
    
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        system("pause");
        return 0;
    }
    
    //合并
    void merge(int *arr, int *tempArr, int left, int mid, int right)
    {
        int l = left; //标记左半区第一个未排序元素
        int r = mid+1;//标记右半区第一个未排序元素
        int t_pos = left;//临时数组的下标
    
        //合并
        while ((l <= mid)&&(r <= right))
        {
            if (arr[l] <= arr[r])
            {
                tempArr[t_pos++] = arr[l++];
            }
            else
            {
                tempArr[t_pos++] = arr[r++];
            }
        }
    
        //合并左半区剩余的元素
        while (l <= mid)
        {
            tempArr[t_pos++] = arr[l++];
        }
    
        //合并右半区剩余的元素
        while (r <= right)
        {
            tempArr[t_pos++] = arr[r++];
        }
    
        //把临时数组的元素放入原数组
        while (left <= right)
        {
            arr[left] = tempArr[left];
            left++;
        }
    }
    
    //归并排序
    void mSort(int *arr, int *tempArr, int left, int right)
    {
        if (left<right)
        {
            int mid = (left+right)/2;
            mSort(arr, tempArr, left, mid); //递归划分左半区域
            mSort(arr, tempArr, mid+1, right); //递归划分右半区域
            merge(arr, tempArr, left, mid, right); //合并部分
        }
    
        return;
    }
    
    //入口函数
    void mergeSort(int *arr, int size)
    {
        int *tempArr = new int[sizeof(int)*size];
        if (tempArr != NULL)
        {
            mSort(arr, tempArr, 0, size-1);
            delete []tempArr;
        }
    
        return;
    }
    

基数排序

参照:https://www.bilibili.com/video/BV1T4411A7Fy?p=13

  1. 原理:先分配再收集
  2. 步骤:按个位数的大小从小到大分配,然后把数据顺序收集起来;把上一步数据按十位数的大小从小到大分配,然后把数据顺序收集起来……依次类推,你数据有多少位,就收集分配几次
    #include <iostream>
    
    using namespace std;
    
    int Max(int arr[], size_t size);
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        //二维数组用来分配数据
        int tempArr[10][arrayLength];
        //统计数组用来标记二维数组每个tempArr[index][]有多少个元素
        int count[10] = {0};
    
        //确定排序轮次
        int max = Max(array, arrayLength);
        int rounds = 0;
        //cout << "max: " << max << endl;
        while ( max!=0 )
        {
            max = max/10;
            rounds++;
        }
        //cout << "rounds: " << rounds << endl;
    
        for (size_t i = 0, n = 1; i < rounds; i++, n*=10)
        {
            for (size_t j = 0; j < arrayLength; j++)
            {
                //确定每个位上的数据
                int number = array[j]/n%10;
                //分配数据
                tempArr[number][count[number]++] = array[j];
            }
            //收集二位数组里面的元素
            int index = 0;
            for (size_t k = 0; k < 10; k++)
            {
                if (count[k] != 0)
                {
                    for (size_t h = 0; h < count[k]; h++)
                    {
                        array[index++] = tempArr[k][h];
                    }
                    count[k] = 0;//拿完元素后将标记值变为0
                }            
            }      
        }
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        return 0;
    }
    
    int Max(int arr[], size_t size)
    {
        int max = arr[0];
        for (size_t i = 1; i < size; i++)
        {
            max = max>arr[i]?max:arr[i];
        }
    
        return max;
    }
    

堆排序

参照:https://www.bilibili.com/video/BV1T4411A7Fy?p=14&spm_id_from=pageDriver

  1. 基础概念:
    • 大顶堆:所有根节点大于两个字节点
    • 小顶堆:所有根节点小于两个字节点
  2. 步骤:
    • 将数组看做一个完全二叉树
    • 将完全二叉树构造为一个大顶堆
    • 将根节点与末尾元素交换
    • 将剩余n-1个元素重复上述两个步骤,直到最后一个元素后这个序列便有序了
    #include <iostream>
    
    using namespace std;
    
    void toMaxHeap(int arr[], int size, int index);
    
    int main()
    {
        int arrayLength = 6;
        int array[arrayLength] = {10,2,5,80,35,60};
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        //定义开始调整的位置
        int startIndex = (arrayLength-2)/2;
        //循环调整,将数组变成一个大顶堆
        for (int i = startIndex; i >= 0; i--)
        {
            toMaxHeap(array, arrayLength, i);
        }
    
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        //把根元素和最后一个元素调换
        for (int i = arrayLength-1; i >= 0; i--)
        {
            int temp = array[0];
            array[0] = array[i];
            array[i] = temp;
            //换完再把剩余元素调成大顶堆
            toMaxHeap(array, i, 0);
        }
        
        for (int i = 0; i < arrayLength; i++)
        {
            cout << array[i] << " ";
        }
        cout << endl;
    
        return 0;
    }
    
    void toMaxHeap(int arr[], int size, int index)
    {
        if (index >= size)
        {
            return;
        }
        
        //获取左右字节点的索引
        int leftNodeIndex = index*2+1;
        int rightNodeIndex = index*2+2;
    
        int maxIndex = index;
    
        //查找最大节点对应的索引
        if (leftNodeIndex<size && arr[leftNodeIndex]>arr[maxIndex])
        {
            maxIndex = leftNodeIndex;
        }
        if (rightNodeIndex<size && arr[rightNodeIndex]>arr[maxIndex])
        {
            maxIndex = rightNodeIndex;
        }
    
        //调换位置
        if (maxIndex != index)
        {
            int temp = arr[maxIndex];
            arr[maxIndex] = arr[index];
            arr[index] = temp;
            //调完位置后可能会影响到后面的树不是大顶堆
            toMaxHeap(arr, size, maxIndex);
        }
        
    }
    
posted @ 2022-06-08 10:20  呆XX  阅读(29)  评论(0编辑  收藏  举报