• ACM算法笔记(六)排序算法【上】


    重点是快速排序堆排序

    一、冒泡排序

            思路:重复地遍历要排序的数列,若其顺序不对则将其进行交换(元素经过交换浮至数列顶端)

            特点:两层嵌套循环,循环内比较交换

    1. public void BubbleSort(int[] arr)
    2. {
    3. for(int i=0; i<arr.lenght; i++)
    4. for(int j=0; j<arr.lenght-1 ;j++) //双层遍历
    5. if(arr[j]>arr[j+1])
    6. {
    7. int temp = arr[j];
    8. arr[j]=arr[j+1];
    9. arr[j+1]=temp; //交换
    10. }
    11. }

            改进:为了减少嵌套循环内层循环的次数,可以略过已排序好的数列(表现在令内层循环的计数元素 j 每次从 i+1起)

    1. public void BubbleSort(int[] arr)
    2. {
    3. for(int i=0; i<arr.lenght; i++)
    4. for(int j=i; j<arr.lenght-1 ;j++) //双层遍历
    5. if(arr[j]>arr[j+1])
    6. {
    7. int temp = arr[j];
    8. arr[j]=arr[j+1];
    9. arr[j+1]=temp; //交换
    10. }
    11. }

    二、选择排序

            选择排序可以看成是优化过的冒泡排序

            步骤如下:      ①找到最大(小)的元素

                                    ②将至与第一个元素交换位置

                                    ③在剩下的数组中重复①②

            与冒泡排序的区别:直接一步到位移动而不是逐个移动;交换需要在内层元素完成遍历后进行

    1. public void ChoiceSort(int[] arr)
    2. {
    3. for(int i=0; i<arr.length; i++)
    4. {
    5. int miniIndex = 0;//最小元素下标
    6. for(int j=i; j<arr.length; j++)
    7. if(arr[j]<arr[miniIndex])
    8. miniIndex = j;
    9. //遍历所有元素,进行交换
    10. int temp = arr[miniIdex];
    11. arr[miniIndex] = arr[i];
    12. arr[i] = temp;
    13. }
    14. }

    三、插入排序

            并不是比较交换排序,而是通过找到合适位置将元素进行插入;适合接近有序数列使用,也适用于小规模数据

            步骤如下:      ①标注需排序的元素,将其前方的序列视为已排序序列(从0开始)

                                    ②将需排序的元素进行比较,找到合适的插入位置,将此位置起的所有已排序序列后移一位

                                    ③将待排序元素插入到后移序列的前方

            特点:比较会在找到合适的位置终止(而不遍历整个序列)

    1. public void InsertSort(int[] arr)
    2. {
    3. int currValue; //当前待排序元素
    4. for(int i=0; i < arr.length-1; i++)
    5. {
    6. int preIndex = i;//标记已被排序的序列
    7. currValue = arr[preIndex+1]; //赋值待排序元素
    8. //进行比较,将合适位置后的数据后移
    9. while(preIndex >=0 && currVaule < arr[preIndex])
    10. {
    11. arr[preIndex +1] = arr[preIndex];
    12. preIndex--;
    13. }
    14. //后移结束,将元素插入新位置
    15. arr[preIndex + 1] = currValue;
    16. }
    17. }

    四、快速排序

            是对冒泡排序的一种改进,采用分治法

            步骤如下:      ①选取一个数据作为基准数,将大的放后面小的放前面(称为分区)

                                    ②对分割的两个部分分别重复步骤①

    1. public void QuickSort(int[] arr,int start,int end)
    2. {
    3. int zoneIndex = partition(arr,start,end);//快速分割+交换
    4. if(zoneIndex > start)
    5. QuickSort(arr,start,zoneIndex-1);//半区快排
    6. if(zoneIndex < end)
    7. QuickSort(arr,zoneIndex+1 ,end);/半区快排
    8. }
    9. private int partition(int[] arr,int start,int end)
    10. {
    11. if(start==end) return start;//单个元素无需分组
    12. int pivot = (start + Math.random()*(end-start+1));//选取一个随机数
    13. int zoneIndex = start-1;
    14. swap(arr,pivot,end);//将基准数与分区尾元素交换位置
    15. for(int i=start;i<=end;i++)
    16. {
    17. if(arr[i]<=arr[end])//计数器+1,但无需交换
    18. zoneIndex++;
    19. if(i > zoneIndex)
    20. swap(arry,i,zoneIndex);//左右互换
    21. }
    22. return zoneIndex;
    23. }

    五、希尔排序

            基于插入排序,将需要排序的数组进行分组,对分组内部进行插入排序;随后将分组扩大(个数减少)再次进行插入排序,直至只剩下一个分组。

            增量(组数)选择 gap=length/2 <折半,但是不一定这么选择>

            分组:两两一组,每组成员间的下标相差gap(如图gap=7,同色元素为一组)

             随后gap=7/2=3,使用3进行分组插入排序

    1. public void ShellSort(int[] arr)
    2. {
    3. int len=arr.length;
    4. int currValue,gap=len/2;//获取分组步长
    5. while(gap>0)
    6. {
    7. for(int i =gap; i<len; i++)
    8. {
    9. currValue = arr[i];//标记当前元素
    10. int preIndex = i - gap;//标记组内已被排序的序列
    11. while(preIndex>=0 && arr[preIndex] > currValue)
    12. {
    13. arr[preIndex + gap] = arr[preIndex];
    14. preIndex -= gap;
    15. }
    16. arr[preIndex + gap] =currValue; //while结束说明找到了合适的位置
    17. }
    18. gap /= 2;
    19. }
    20. }
  • 相关阅读:
    数据结构:二叉树(3):相关oj题目
    【Spark NLP】第 9 章:信息提取
    Windows OpenGL ES 图像饱和度调节
    飞浆从入门到实战1-环境搭建
    Java项目:ssm物业管理系统
    【无标题】
    【需求侧响应】综合能源中多种需求响应——弹性电价、可平移及可削减研究(Matlab代码实现)
    C++指针访问数组 & 函数中用指针传参
    C++auto 关键字
    内存取证入门第一题
  • 原文地址:https://blog.csdn.net/weixin_37878740/article/details/124913532