算法:排序算法

本文深入探讨了内部排序算法,包括插入排序、选择排序、冒泡排序、快速排序、归并排序和基数排序等,详细解释了各种算法的思想、实现代码及优化方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 内部排序
    1. 插入排序
      1. 思想:将n个数组看成一个有序表和一个无序表,开始时有序表只有一个元素,排序过程是每次取出无序表中的第一个元素,将它的排序码与有序表中元素的排序码进行比较,将其放在合适的位置
        public static void insertSort(int[] array) {
            for (int i = 1;i<array.length;i++){
                int insertIndex=i-1;
                int insertVal=array[i];
                while (insertIndex>=0&&insertVal<=array[insertIndex]){
                    array[insertIndex+1]=array[insertIndex];
                    insertIndex--;
                }
                array[++insertIndex]=insertVal;
            }
        }

         

      2. 直接插入排序
      3. 希尔排序
    2. 选择排序
      1. 思想:对于数组arr[n],从小到大:第一次从从arr[0]到arr[n-1]选一个最小值与arr[0]交行,第二次从arr[1]到arr[n-1]选一个最小值与arr[1]交换,以此类推,通过n-1次得到有序序列。从大到小排序,与从小到大的方式一样,只是每次选出最大值
        public static void selectSort(int[] array) {
            for (int i = 0;i<array.length-1;i++){
                int min=array[i];
                int minIndex=i;
                for (int j = i+1;j<array.length;j++){
                    if(array[j]<min){
                        min=array[j];
                        minIndex=j;
                    }
                }
                if(minIndex!=i){
                    array[minIndex]=array[i];
                    array[i]=min;
                }
            }
        }
      2. 简单选择排序
      3. 堆排序
    3. 交换排序
      1. 冒泡排序
        1. 代码
          public static void bubbleSort(int[] array) {
              //
              for(int i = 0;i<array.length;i++){
                  //
                  for(int j = 0;j<array.length-i-1;j++){
                      if(array[j]>array[j+1]){
                          int temp = array[j];
                          array[j]=array[j+1];
                          array[j+1]=temp;
                      }
                  }
              }
          }
        2. 优化:在每轮循环过程中,若有元素有交换,数列无序;若无元素交换,说明数列已然有序,直接跳出大循环
          public static void bubbleSort(int[] array) {
              //数组循环的轮数
              for (int i = 0;i<array.length;i++){
                  //有序标记,每轮初始值都是true
                  boolean flag = true;
                  for (int j = 0;j<array.length-i-1;j++){
                      if(array[j]>array[j+1]){
                          int temp = array[j];
                          array[j]=array[j+1];
                          array[j+1]=temp;
                          //若数组不是有序的将有序标记设置为false
                          flag = false;
                      }
                  }
                  //有序标记为true时,说明数组是有序的,跳槽循环
                  if(flag){
                      break;
                  }
              }
          }
        3. 优化:添加边界,每轮循环后,边界之后的元素肯定是有序的,无须比较,所以下轮循环时只需要比较边界前的数列
          public static void bubbleSort(int[] array) {
              //最后一次交换的位置
              int lastExchangeIndex = 0;
              //边界下标,边界前面的为无序数列,边界后面的为有序数列,每轮循环只需要比到此处
              int sortBorder=array.length-1;
              //数组循环的轮数
              for (int i = 0;i<array.length;i++){
                  //有序标记,每轮初始值都是true
                  boolean flag = true;
                  for (int j = 0;j<sortBorder;j++){
                      if(array[j]>array[j+1]){
                          int temp = array[j];
                          array[j]=array[j+1];
                          array[j+1]=temp;
                          //若数组不是有序的将有序标记设置为false
                          flag = false;
                          //最后一次交换的位置
                          lastExchangeIndex = j;
                      }
                  }    
                  //有序标记为true时,说明数组是有序的,跳槽循环
                  if(flag){
                      break;
                  }
                  //每轮循环后,将边界设置为最后交换的位置
                  sortBorder=lastExchangeIndex;
              }
          }
        4. 升级:鸡尾酒排序
          public static void bubbleSort(int[] array) {
              //左边界,边界左边为有序数列
              int leftSortBorder=0;
              //右边界,边界右边为有序数列
              int rightSortBorder=array.length-1; 
              //向右比对时最后一次交换的位置
              int lastRightExchangeIndex =0;
              //向左比对时最后一次交换的位置
              int lastLeftExchangeIndex =0;
          
              for (int i = 0;i<array.length;i++){
                  boolean flag = true;
                  //从左往右,大的向后移动
                  for (int j = leftSortBorder;j<rightSortBorder;j++){
                          if(array[j]>array[j+1]){
                          int temp = array[j];
                          array[j]=array[j+1];
                          array[j+1]=temp;
                          lastRightExchangeIndex=j;
                          flag=false;
                  }
              }
              rightSortBorder=lastRightExchangeIndex;
              if(flag){
                  break;
              }
              //从右往左,小的向前移动
              flag = true;
              for (int j = rightSortBorder;j>leftSortBorder;j--){
                  if(array[j]<array[j-1]){
                      int temp = array[j];
                      array[j]=array[j-1];
                      array[j-1]=temp;
                      lastLeftExchangeIndex=j;
                      flag=false;
                  }
                }
                leftSortBorder=lastLeftExchangeIndex;
                if(flag){
                    break;
                }
              }
          }
      2. 快速排序
    4. 归并排序
    5. 基数排序
      1. 介绍:
        1. 属于分配式排序
        2. 效率高的稳定性排序
        3. 桶排序的扩展
        4. 以空间换时间,可能会出现OutOfMemoryError错误
      2. 思想:将数组中所有的数据统一为同样的数位长度,数位较短的数前面补零,然后从最低位开始比较,依次进行排序,直到最高位排序完成后,数列就是一个有序的数列
      3. 例子:数组{26,8,500},排序后{8,26,500}
      4. 代码:
        public static void radixSort(int[] array) {
            //获取最大元素的位数
            int max = array[0];
            int arrLength = array.length;
            for (int i =1;i<arrLength;i++){
                if(array[i]>max){
                    max=array[i];
                }
            }
            int maxLenght=(max+"").length();
        
            //二维数组表示10个桶,每个桶都是一个一位数组,存放array中的元素
            int[][] bucket = new int[10][arrLength];
            //桶中每次放入的数据个数
            int[] bucketElementCounts = new int[10];
                
            //排序
            for (int i =0,n=1;i<maxLenght;i++,n*=10){
                    
                //将元素放到桶中
                for (int j = 0;j<arrLength;j++){
                    //元素各位的值,各位、十位、百位...
                    int digitOfElement = array[j]/n % 10;
                    //将元素放到对应的桶中
                    bucket[digitOfElement][bucketElementCounts[digitOfElement]]=array[j];
                    bucketElementCounts[digitOfElement]++;
                }
        
               int index = 0;
               //遍历桶
               for(int j = 0;j<10;j++){
                   //如果桶中有元素,遍历桶,此处必须用bucketElementCounts[j]
                   if(bucketElementCounts[j]>0){
                       //依次将桶中的元素放到原数组中
                       for(int k = 0;k<bucketElementCounts[j];k++){
                           array[index++]=bucket[j][k];
                       }
                    }
                    //将桶中的元素的个数置为0
                    bucketElementCounts[j]=0;
                }
            }
        
        }
  2. 外部排序
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值