• 基本数据结构与算法实现JavaAPI【2】-----排序篇


    在本篇章中不阐释原理,仅阐述使用java语言实现。

    1.冒泡排序(时间复杂度:O(N^2);稳定):

    1. public class sort00 {
    2. public static void sort(Comparable[] a){
    3. for(int i=a.length-1;i>0;i--){
    4. for(int j=0;j<i;j++){
    5. if(greater(a[j],a[j+1])){
    6. exch(a,j,j+1);
    7. }
    8. }
    9. }
    10. }
    11. private static void exch(Comparable[] a, int i, int j) {
    12. Comparable temp=a[i];
    13. a[i]=a[j];
    14. a[j]=temp;
    15. }
    16. private static boolean greater(Comparable a, Comparable b) {
    17. return a.compareTo(b)>0;
    18. }
    19. }

    冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行,直到没有相邻元素需要交换,也就是说该元素列已经排序完成。(出自百度百科)


    2.选择排序:(时间复杂度:O(N^2);不稳定):

    1. public class sort01 {
    2. public static void sort(Comparable[] a){
    3. for (int i = 0; i <a.length-1 ; i++) {
    4. int minindex=i;
    5. for(int j=i+1;j<a.length;j++){
    6. if(greater(a[minindex],a[j])){
    7. minindex=j;
    8. }
    9. }
    10. exch(a,i,minindex);
    11. }
    12. }
    13. private static void exch(Comparable[] a, int i, int j) {
    14. Comparable temp=a[i];
    15. a[i]=a[j];
    16. a[j]=temp;
    17. }
    18. private static boolean greater(Comparable a, Comparable b) {
    19. return a.compareTo(b)>0;
    20. }
    21. }

    选择排序(Selection sort)是一种简单直观的排序算法。它的工作原理是:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾。以此类推,直到全部待排序的数据元素的个数为零。选择排序是不稳定的排序方法。(出自百度百科)

    3.插入排序:(时间复杂度:O(N^2);稳定)

    1. public class sort02 {
    2. public static void sort(Comparable[] a){
    3. for (int i = 0; i < a.length - 1; i++) {
    4. for (int j = i; j >=0 ; j--) {
    5. if(geater(a[j],a[j+1])){
    6. exch(a,j,j+1);
    7. }
    8. }
    9. }
    10. }
    11. private static void exch(Comparable[] a,int i,int j){
    12. Comparable temp=a[i];
    13. a[i]=a[j];
    14. a[j]=temp;
    15. }
    16. private static boolean geater(Comparable a,Comparable b){
    17. return a.compareTo(b)>0;
    18. }
    19. }

    插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 [1]  。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动(出自百度百科)

    4.希尔排序(不稳定)

    1. public class sort03 {
    2. public static void sort(Comparable[] a){
    3. //1.由数组a的长度确定增长量h的初始值
    4. int h=1;
    5. while (h<a.length/2){
    6. h=2*h+1;
    7. }
    8. //2.希尔排序
    9. while (h>=1){
    10. //排序
    11. //找到待插入的元素
    12. for (int i = h; i < a.length; i++) {
    13. //把待插入的元素插入到有序数列中
    14. for (int j = i; j >=h ; j-=h) {
    15. //带插入元素是a[j],比较a[j]和a[j-h]
    16. if(geater(a[j-h],a[j])){
    17. //交换元素
    18. exch(a,j-h,j);
    19. }else {
    20. //待插入元素已经找到了合适的位置,结束循环
    21. break;
    22. }
    23. }
    24. }
    25. //减小h的值
    26. h=h/2;
    27. }
    28. }
    29. private static void exch(Comparable[] a,int i,int j){
    30. Comparable temp=a[i];
    31. a[i]=a[j];
    32. a[j]=temp;
    33. }
    34. private static boolean geater(Comparable a,Comparable b){
    35. return a.compareTo(b)>0;
    36. }
    37. }

    希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至 1 时,整个文件恰被分成一组,算法便终止(出自百度百科)

    5.归并排序:时间复杂度为o(nlog(n))

    1. public class sort04 {
    2. //归并排序所需要的辅助数组
    3. private static Comparable[] assist;
    4. //比较v元素是否小于w元素
    5. private static boolean less(Comparable v,Comparable w){
    6. return v.compareTo(w)<0;
    7. }
    8. // 数组元素i和j交换位置
    9. private static void exch(Comparable[] a,int i,int j){
    10. Comparable t=a[i];
    11. a[i]=a[j];
    12. a[j]=t;
    13. }
    14. // 对数组a中元素进行排序
    15. public static void sort(Comparable[] a){
    16. //1.初始化辅助数组assist
    17. assist=new Comparable[a.length];
    18. //2.定义一个lo变量和hi变量,分别记录数组中最小索引和最大索引
    19. int lo=0;
    20. int hi=a.length-1;
    21. //3.调用sort重载方法完成数组a中,从实验lo到索引hi的元素的排序
    22. sort(a,lo,hi);
    23. }
    24. // 对数组a中从lo到hi的元素进行排序
    25. private static void sort(Comparable[] a,int lo,int hi){
    26. if(hi<=lo){
    27. return;
    28. }
    29. // 对lo到hi之间的数据分为两个组
    30. int mid=lo+(hi-lo)/2;
    31. // 分别对每一组数据排序
    32. sort(a,lo,mid);
    33. sort(a,mid+1,hi);
    34. // 把两个组中的数据进行归并
    35. merge(a,lo,mid,hi);
    36. }
    37. // 对数组中从lo到mid为一组,从mid+1到hi为一组,对这两组数据进行归并
    38. private static void merge(Comparable[] a,int lo,int mid,int hi){
    39. //定义三个指针
    40. int i=lo,p1=lo,p2=mid+1;
    41. //遍历移p1指针和p2指针,比较对应索引处的值,找出最小的一个,放到辅助数组的对应索引处
    42. while (p1<=mid && p2<=hi){
    43. //比较对应索引处的值
    44. if(less(a[p1],a[p2])){
    45. assist[i++]=a[p1++];
    46. }else {
    47. assist[i++]=a[p2++];
    48. }
    49. }
    50. //遍历,若p1指针没有走完,那么顺序移动p1指针,把对应的元素放到辅助数组的对应索引处
    51. while (p1<=mid){
    52. assist[i++]=a[p1++];
    53. }
    54. //遍历,若p2指针没有走完,那么顺序移动p2指针,把对应的元素放到辅助数组的对应索引处
    55. while (p2<=hi){
    56. assist[i++]=a[p2++];
    57. }
    58. //把辅助数组中元素复制到原数组中
    59. for (int index = lo; index <=hi ; index++) {
    60. a[index]=assist[index];
    61. }
    62. }
    63. }

    归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并(出自百度百科)

    6.快速排序

    1. public class sort05 {
    2. //比较v元素是否小于w元素
    3. private static boolean less(Comparable v,Comparable w){
    4. return v.compareTo(w)<0;
    5. }
    6. // 数组元素i和j交换位置
    7. private static void exch(Comparable[] a,int i,int j){
    8. Comparable t=a[i];
    9. a[i]=a[j];
    10. a[j]=t;
    11. }
    12. // 对数组a中元素进行排序
    13. public static void sort(Comparable[] a){
    14. int lo=0;
    15. int hi=a.length-1;
    16. sort(a,lo,hi);
    17. }
    18. // 对数组a中从lo到hi的元素进行排序
    19. private static void sort(Comparable[] a,int lo,int hi){
    20. //安全性校验
    21. if(hi<=lo){
    22. return;
    23. }
    24. //需要对数组中lo索引到hi索引出的元素进行分组(左子组和右子组)
    25. int partition = partition(a, lo, hi);//返回的是分组分界值所在的索引,分界值位置变换后的索引
    26. //让左子组有序
    27. sort(a,lo,partition-1);
    28. //让右子组有序
    29. sort(a,partition+1,hi);
    30. }
    31. // 对数组a中,从索引lo到索引hi之间的元素进行分组,并返回分组界限对应的索引
    32. public static int partition(Comparable[] a,int lo,int hi){
    33. //确定分界值
    34. Comparable key =a[lo];
    35. //对应两个指针,分别指向待切分元素的最小索引处和最大索引处的下一个位置
    36. int left=lo;
    37. int right=hi+1;
    38. //切分
    39. while (true){
    40. //先从右往左扫描,移动right指针,找到一个比分界值小的元素,停止
    41. while (less(key,a[--right])){
    42. if(right==lo){
    43. break;
    44. }
    45. }
    46. //在从左往右扫描,移动left指针,找到一个比分界值大的元素,停止
    47. while (less(a[++left],key)){
    48. if(left==hi){
    49. break;
    50. }
    51. }
    52. // 判断left>=right;如果成立则证明元素扫描完毕结束循环。若不成立,则交换元素即可
    53. if(left>=right){
    54. break;
    55. }else {
    56. exch(a,left,right);
    57. }
    58. }
    59. //交换分界值
    60. exch(a,lo,right);
    61. return right;
    62. }
    63. }

    快速排序(Quicksort),计算机科学词汇,适用领域Pascal,c++等语言,是对冒泡排序算法的一种改进(出自百度百科)

    几种排序算法小节:

    排序的稳定性:
        在乱序数组中,相等元素A,B在排序之后,其位置保持不变,表明此排序算法是稳定的
    稳定性的意义:
        在多次排序情况下需要使用稳定性的算法,意义在于可以最大保留排序后的结果,减小内存开销

    稳定排序:
        冒泡、插入、归并、

    快速排序和归并排序的区别:
                1.归并:先等数量分组各自排序,将分别拍好序的子数组再重新排序成原数组
                2.快排:先按标准值分组,这个组不一定是等数量分组,分好组后再各自排序,当所有组拍好序,本数组就有序
            时间复杂度:
                等分最优:o(nlog(n))
                有多少个元素切多少组最坏:o(n^2)
                平均复杂度o(nlog(n))

  • 相关阅读:
    C++-指针:void*(不确定类型指针)简介【void *可以接受任何类型的赋值】【void *可以赋值给任何类型的变量】【void *不可以解引用】
    部署bpmn项目实现activiti流程图的在线绘制
    Android:OkHttp同步请求和异步请求
    TypeScript深度剖析:TypeScript 中接口的理解?应用场景?
    MAVEN-ERE一个新的事件关系检测数据集
    数据安全服务是什么意思?
    安装kubesphere3.3
    面试被经常问的SQL窗口函数!
    Android API 30及更高版本网络权限设置
    十大常见排序算法详解(附Java代码实现和代码解析)
  • 原文地址:https://blog.csdn.net/qq_55865959/article/details/125828859