七大基于比较的排序算法(JAVA)

简介: 冒泡排序堆排序插入排序希尔排序归并排序快速排序选择排序 

排序算法的稳定性大小相同的元素在排序前后相对位置相同就称其为稳定的排序。

注:一个本身就是稳定的排序 是可以实现为不稳定的排序的 ;但是相反 一个本身就不稳定的排序 是不可能实现为稳定的排序的。

稳定的排序算法:插入排序 冒泡排序 归并排序

冒泡排序

时间复杂度: o(n^2)   如果加了优化  最好情况O(N)

空间复杂度:O(1)

稳定性: 稳定

publicstaticvoidbubbleSort(int[] array){
for (inti=0; i<array.length-1; i++) {
for (intj=0; j<array.length-1; j++) {
if (array[j] >array[j+1]) {
swap(array, j, j+1);
                }
            }
        }
    }
privatestaticvoidswap(int[] array, intminIndex, inti) {
inttmp=array[i];
array[i] =array[minIndex];
array[minIndex] =tmp;
    }

image.gif

优化:

publicstaticvoidbubbleSort(int[] array) {
for (inti=0; i<array.length-1; i++) {
booleanflg=false;
for (intj=0; j<array.length-1-i; j++) {
if(array[j] >array[j+1]) {
swap(array,j,j+1);
flg=true;
                }
            }
if(!flg) {
return;
            }
        }
    }

image.gif

堆排序

时间复杂度:O(n*logN)    N^1.3 -->

空间复杂度:O(1)

稳定性:不稳定

数据量非常 大的时候 堆排 一定比希尔快


堆排序的原理:

    1. 用一个大根堆的堆顶元素和最后一个元素交换
    2. 使数组长度减一
    3. 在重新将堆调整为大根堆

    image.gif

    publicstaticvoidheapSort(int[] array){
    createHeap(array);
    for (inti=0; i<array.length-1; i++) {
    swap(array, 0, array.length-1-i);
    shiftDown(array, 0, array.length-1-i);
            }
        }
    privatestaticvoidcreateHeap(int[] array) {
    for (inti= (array.length-1-1)/2; i>=0; i--) {
    shiftDown(array, i, array.length);
            }
        }
    privatestaticvoidshiftDown(int[] array, inti, intlength) {//length个元素intchild=i*2+1;
    while (child<length) {
    if (child+1<length&&array[child] <array[child+1]) {
    child++;
                }
    if (array[child] >array[i]) {
    swap(array, child, i);
    i=child;
                }else {
    break;
                }
    child=i*2+1;
            }
        }
    privatestaticvoidswap(int[] array, intminIndex, inti) {
    inttmp=array[i];
    array[i] =array[minIndex];
    array[minIndex] =tmp;
        }

    image.gif

    插入排序

    时间复杂度:

           最好情况:数据完全有序的时候 O(N)

           最坏情况:数据完全逆序的时候 O(N^2)

    空间复杂度:O(1)

    稳定性:稳定

    插入排序的原理

      1. 从左边第一位开始挨个令其成为关键码
      2. 从左到右把待排序的记录按其关键码值的大小逐个插入到左边已经排好序的有序序列中
      3. 直到所有的记录插入完为止,得到一个新的有序序列
      publicstaticvoidinsertSort(int[] array){
      for (inti=1; i<array.length; i++) {
      inttmp=array[i];
      intj=i-1;
      for (; j>=0 ; j--) {
      //如果此处改为array[j] >= tmp就会变成不稳定排序if (array[j] >tmp) {
      array[j+1] =array[j];
                      }else{
      break;
                      }
                  }
      array[j+1] =tmp;
              }
          }

      image.gif

      希尔排序

      时间复杂度:

                  约等于:n^1.3 - n^1.5

      复杂度:O(1)

      稳定性:不稳定

      希尔排序其实就是对插入排序的一种优化

      基本原理:

        1. 先按照步长将数组分为若干组
        2. 对每组进行插入排序
        3. 减小步长重复以上步骤

        image.png

        publicstaticvoidshellSort(int[] array){
        intgap=array.length;
        while (gap>1) {
        gap=gap/2;
        shell(array, gap);
                }
            }
        privatestaticvoidshell(int[] array, intgap) {
        for (inti=gap; i<array.length; i++) {
        inttmp=array[i];
        intj=i-gap;
        for (; j>=0; j-=gap) {
        if (array[j] >tmp) {
        array[j+gap] =array[j];
                        }else {
        break;
                        }
                    }
        array[j+gap] =tmp;
                }
            }

        image.gif

        归并排序


        时间复杂度: 0(N*logN)

        空间复杂度:O(n)

        稳定性: 稳定


        归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。

        publicvoidmergerSort(int[] nums, intleft, intright) {//right:数组长度减一if (left>=right) {
        return;
                }
        intmid= (left+right) /2;
        mergerSort(nums, left, mid);
        mergerSort(nums, mid+1, right);
        merger(nums, left, mid, right);
            }
        privatevoidmerger(int[] nums, intleft, intmid, intright) {
        int[] tmp=newint[right-left+1];
        inti=0;
        intl=left;
        intr=mid+1;
        while (l<=mid&&r<=right) {
        if (nums[l] <nums[r]) {
        tmp[i++] =nums[l++];
                    }else {
        tmp[i++] =nums[r++];
                    }
                }
        while (l<=mid) {
        tmp[i++] =nums[l++];
                }
        while (r<=right) {
        tmp[i++] =nums[r++];
                }
        i=0;
        for (intj=0; j<tmp.length; j++) {
        nums[left++] =tmp[j];
                }
            }

        image.gif

        快速排序

        时间复杂度:

               最好情况:O(N*logN)   满二叉树/完全二叉树

               最坏情况:O(N^2) 单分支的树

        空间复杂度:

               最好情况:O(logN)   满二叉树/完全二叉树

               最坏情况:O(N)   单 分支的树

        稳定性:不稳定

        快速排序基本原理

          1. 任取待排序元素序列中的某元素作为基准值
          2. 按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值
          3. 每个子序列重复该过程,直到所有元素都排列在相应位置上为止

          有Hoare法   挖坑版法  前后指针法

          这里只介绍Hoare法

          publicstaticvoidquickSort(int[] array){
          quick(array, 0, array.length-1);
              }
          privatestaticvoidquick(int[] array, intleft, intright) {
          if (left>=right) {
          return;
                  }
          intIndex=findSwap(array, left, right);
          quick(array, left, Index-1);
          quick(array, Index+1, right);
              }
          privatestaticintfindSwap(int[] array, intleft, intright) {
          intkey=array[left];
          intkeyIndex=left;
          while (left<right) {
          //必须right先走//如果是left先走,两个相遇的地方一定比key大while (left<right&&array[right] >=key) {
          right--;
                      }
          while (left<right&&array[left] <=key) {
          left++;
                      }
          swap(array, right, left);
                  }
          if (left==right) {
          swap(array, keyIndex, left);
                  }
          returnleft;
              }
          privatestaticvoidswap(int[] array, intminIndex, inti) {
          inttmp=array[i];
          array[i] =array[minIndex];
          array[minIndex] =tmp;
              }

          image.gif

          优化

          利用三数取中法来避免单分支树的形成(尽量降低树的高度)

          publicint[] sortArray(int[] nums) {
          //快速排序quickSort(nums, 0, nums.length-1);
          returnnums;
              }
          privatevoidquickSort(int[] nums, intleft, intright) {
          if (left>=right) {
          return;
                  }
          //三数取中法swap(nums, left, threeNumMid(nums, left, right));
          //也可以在这里加一个判断当左右之间的数据个数小于一定值然后调用插入排序//因为在排序过程中数组会趋近于有序所以插入排序的效率会很快intpivot=quick(nums, left, right);
          quickSort(nums, left, pivot-1);
          quickSort(nums, pivot+1, right);
              }
          privateintthreeNumMid(int[] nums, intleft, intright) {
          intmid= (left+right) /2;
          if (nums[left] >nums[right]) {
          if (nums[mid] >nums[left]) {
          returnleft;
                      }elseif (nums[mid] <nums[right]) {
          returnright;
                      }else {
          returnmid;
                      }
                  }else {
          if (nums[mid] <nums[left]) {
          returnleft;
                      }elseif (nums[mid] >nums[right]) {
          returnright;
                      }else {
          returnmid;
                      }
                  }
              }
          privateintquick(int[] nums, intleft, intright) {
          intindex=left;
          intkey=nums[left];
          while (left<right) {
          while (left<right&&nums[right] >=key) {
          right--;
                      }
          while (left<right&&nums[left] <=key) {
          left++;
                      }
          swap(nums, right, left);
                  }
          swap(nums, index, left);
          returnleft;
              }
          privatevoidswap(int[] nums, intleft, intright) {
          inttmp=nums[left];
          nums[left] =nums[right];
          nums[right] =tmp;
              }

          image.gif

          选择排序

          时间复杂度:O(n^2)

          空间复杂度:O(1)

          稳定性:不稳定的排序

          选择排序基本原理:

            1. 从左至右每一次从待排序的数据元素中选出最小(或最大)的一个元素
            2. 将其放在待排序元素的起始位置,已有序元素的最后边
            3. 重复上述步骤直到全部待排序的数据元素排完 。
            publicstaticvoidselectSort(int[] array){
            for (inti=0; i<array.length; i++) {
            intminIndex=i;
            for (intj=i+1; j<array.length; j++) {
            if (array[minIndex] >array[j]) {
            minIndex=j;
                            }
                        }
            swap(array, minIndex, i);
                    }
                }
            privatestaticvoidswap(int[] array, intminIndex, inti) {
            inttmp=array[i];
            array[i] =array[minIndex];
            array[minIndex] =tmp;
                }

            image.gif

            目录
            相关文章
            |
            2月前
            |
            算法 搜索推荐 Java
            数据结构与算法(Java篇)笔记--希尔排序
            数据结构与算法(Java篇)笔记--希尔排序
            |
            2月前
            |
            算法 Java
            [Java·算法·简单] LeetCode 27. 移除元素 详细解读
            [Java·算法·简单] LeetCode 27. 移除元素 详细解读
            23 1
            |
            2月前
            |
            算法 Java
            [Java·算法·简单] LeetCode 13. 罗马数字转整数 详细解读
            [Java·算法·简单] LeetCode 13. 罗马数字转整数 详细解读
            23 0
            |
            2月前
            |
            算法 Java
            [Java·算法·简单] LeetCode 392. 判断子序列 详细解读
            [Java·算法·简单] LeetCode 392. 判断子序列 详细解读
            31 0
            |
            2月前
            |
            存储 canal 算法
            [Java·算法·简单] LeetCode 125. 验证回文串 详细解读
            [Java·算法·简单] LeetCode 125. 验证回文串 详细解读
            23 0
            |
            2月前
            |
            算法 Java
            [Java·算法·中等] LeetCode15. 三数之和
            [Java·算法·中等] LeetCode15. 三数之和
            30 0
            |
            7天前
            |
            设计模式 算法 Java
            [设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
            [设计模式Java实现附plantuml源码~行为型]定义算法的框架——模板方法模式
            |
            8天前
            |
            搜索推荐 算法 Java
            Java实现的常用八种排序算法
            提到数据结构与算法,无法避免的一点就包含排序,熟练的掌握各种排序算法则是一个程序员必备的素质之一,除此之外,排序算法也是当下各大技术公司比较喜欢问的技术点,所以,就这一点JavaBuild整理了常见的8种排序算法
            6 0
            |
            22天前
            |
            算法 安全 Java
            java代码 实现AES_CMAC 算法测试
            该代码实现了一个AES-CMAC算法的简单测试,使用Bouncy Castle作为安全提供者。静态变量K定义了固定密钥。`Aes_Cmac`函数接受密钥和消息,返回AES-CMAC生成的MAC值。在`main`方法中,程序对给定的消息进行AES-CMAC加密,然后模拟接收ECU的加密结果并进行比较。如果两者匹配,输出&quot;验证成功&quot;,否则输出&quot;验证失败&quot;。辅助方法包括将字节转为16进制字符串和将16进制字符串转为字节。
            |
            29天前
            |
            搜索推荐 Java
            Java排序算法
            Java排序算法
            18 0