算法排序问题。每种排序代表着没中思考问题的方式。我们学习了选择排序,冒泡排序,归并排序。让我们去回顾回顾吧。重在思想的领悟。

简介: 算法排序问题。每种排序代表着没中思考问题的方式。我们学习了选择排序,冒泡排序,归并排序。让我们去回顾回顾吧。重在思想的领悟。

第一个选择排序:想想是先找最大的值,以此类推。如果有五个数他要循环4遍,如果有n个数,他要循环n-1次,效果很低。

package a;
/**
 * 选择排序
 * @author MZFAITHDREAM
 *n^2
 */
public class Arrayxz {
  public static void main (String[] args) {
    int[] arr= {55,82,59,45,532};
    for (int i = 0; i < arr.length -1; i++) {
      int maxpos=i;
    for (int j = i+1; j < arr.length; j++) {
    maxpos =arr[j] >arr[maxpos] ?j:maxpos;
    }
    System.out.println("minpose:"+maxpos);
    swap(arr, i, maxpos);
    System.out.println("经过第"+i+"次循环之后,数据内容");
    print(arr);
    }
  }
  static void swap(int[] arr,int i,int j ) {
    int temp=arr[i]; 
    arr[i]=arr[j];
    arr[j]=temp;
  }
static void print (int [] arr) {
  for (int i = 0; i < arr.length; i++) {
    System.out.print(arr[i] + "  ");
  }
}
}

第二种冒泡排序:

请看我画的图形一组数据,两个相比较,如果前者大于后者换位。

package a;
import java.util.Scanner;
/**
 * 12/6用冒泡方式解决
 * @author MZFAITHDREAM
 *键盘输入5个整数 要求使用冒泡排序将这5个整数从大到小进行排
 *序并输出排序后的结果
 */
public class EngA {
  public static void main(String[] args) {
      Scanner sc=new Scanner(System.in);
      System.out.println("请输入第一个数");
      int a=sc.nextInt();
      System.out.println("请输入第二个数");
      int b=sc.nextInt();
      System.out.println("请输入第三个数");
      int c=sc.nextInt();
      System.out.println("请输入第四个数");
      int d=sc.nextInt();
      System.out.println("请输入第五个数");
      int e=sc.nextInt();
      int []array={a,b,c,d,e};
      for(int i=0;i<(array.length-1);i++)
      {
        for(int j=i+1;j<array.length;j++)
        {
          if(array[i]>array[j])
          {
            int z=array[i];
            array[i]=array[j];
            array[j]=z;
          }else {
          }
        }
      }
      System.out.println("从小到大:"+array[0]+" "+array[1]+" "+array[2]+" "+array[3]+" "+array[4]);
    }
  static void print (int [] arr) {
    for (int i = 0; i < arr.length; i++) {
      System.out.print(arr[i] + "  ");
    }
  }
  }

第三种排序方式归并排序。

 

package com.shuzu;
import java.util.Arrays;
public class Sor5 {
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    int[] arr = new int[]{3,6,4,7,5,2};
        merge(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    //归并
    public static void merge(int[] arr,int low,int high){
        int center = (high+low)/2;
        if(low<high){
            //递归,直到low==high,也就是数组已不能再分了,
            merge(arr,low,center);
            merge(arr,center+1,high);
            //当数组不能再分,开始归并排序
            mergeSort(arr,low,center,high);
            System.out.println(Arrays.toString(arr));
        }
    }
    //排序
    public static void mergeSort(int[] arr,int low,int center,int high){
        //用于暂存排序后的数组的临时数组
        int[] tempArr = new int[arr.length];
        int i = low,j = center+1;
        //临时数组的下标
        int index = 0;
        //循环遍历两个数组的数字,将小的插入到临时数组里
        while(i<=center && j<= high){
            //左边数组的数小,插入到新数组
            if(arr[i]<arr[j]){
                tempArr[index] = arr[i];
                i++;
            }else{//右边数组的数小,插入到新数组
                tempArr[index] = arr[j];
                j++;
            }
            index++;
        }
        //处理左半边数组多余的数据,将左半边多余的数据直接追加的临时数组的后面
        while(i<=center){
            tempArr[index] = arr[i];
            i++;
            index++;
        }
        //处理右半边数组多余的数据,将右半边多余的数据直接追加的临时数组的后面
        while(j<= high){
            tempArr[index] = arr[j];
            j++;
            index++;
        }
        //将临时数组中的数据重新放进原数组
        for (int k = 0; k < index; k++) {
            arr[k+low] = tempArr[k];
        }
  }
}

1.  向上归并排序的时候,需要一个暂存数组用来排序,

2.  将待合并的两个数组,从第一位开始比较,小的放到暂存数组,指针向后移,

3.  直到一个数组空,这时,不用判断哪个数组空了,直接将两个数组剩下的元素追加到暂存数组里,

4.  再将暂存数组排序后的元素放到原数组里,两个数组合成一个,这一趟结束。

第四种方式快速排序。

package com.shuzu;
import java.util.Arrays;
public class Sor4 {
根据思路分析,第一趟的执行流程如下图所示:
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
      int[] arr = new int[]{10,6,3,8,33,27,66,9,7,88};
//        int[] arr = new int[]{1,3,2};
        f(arr,0,arr.length-1);
        System.out.println(Arrays.toString(arr));
    }
    public static void f(int[] arr,int start,int end){
        //直到start>=end时结束递归
        if(start<end){
            int left = start;
            int right = end;
            int temp = arr[start];
            while(left<right){
                //右面的数字大于标准数时,右边的数的位置不变,指针向左移一个位置
                while(left<right && arr[right]>temp){
                    right--;
                }
                //右边的数字及下标小于或等于基本数,将右边的数放到左边
                if(left<right) {
                     arr[left] = arr[right];
                     left++;
                }
                左边的数字小于或等于标准数时,左边的数的位置不变,指针向右移一个位置
                while(left<right && arr[left]<=temp){
                    left++;
                }
                //左边的数字大于基本数,将左边的数放到右边
                arr[right] = arr[left];
            }
            //一趟循环结束,此时left=right,将基数放到这个重合的位置,
            arr[left] = temp;
            //将数组从left位置分为两半,继续递归下去进行排序
            f(arr,start,left);
            f(arr,left+1,end);
        }
  }
}

第五种 希尔排序

package com.shuzu;
import java.util.Arrays;
public class Sor7 {
  /**
   * 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐
   * 渐减少,每组包含的关键词越来越多,当增量减至
   * 1时,整个文件恰被分成一组,算法便终止。
  简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,
插入,比如[5,4,3,2,1,0]这种倒序序列,数组末端的0要回到首位置很是费劲,
比较和移动元素均需n-1次。
  而希尔排序在数组中采用跳跃式分组的策略,通过某个增量将数组元素划分为若干组,然后
分组进行插入排序,随后逐步缩小增量,继续按组进行插入排序操作,直至增量为1。希尔排序通过这
种策略使得整个数组在初始阶段达到从宏观上看基本有序,小的基本在前,大的基本在后。然后缩小增量,到增量为1时,
其实多数情况下只需微调即可,不会涉及过多的数据移动。
  来看下希尔排序的基本步骤,在此选择增量gap=length/2,缩小增量继续以gap = gap/2的方式,这种增量选择可以用一个序列来表示,{n/2,(n/2)/2...1},称为增量序列。希尔排序的增量序列的选择与证明是个数学难题,选择的这个增量序列是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。此处做示例使用希尔增量。
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
     int[] arr = new int[]{10,6,3,8,33,27,66,9,7,88};
          shellSort(arr);
          System.out.println(Arrays.toString(arr));
      }
      private static void shellSort(int[] arr) {
          int temp;
          //控制增量序列,增量序列为1的时候为最后一趟
          for (int i = arr.length/2; i >0; i/=2) {
              //根据增量序列,找到每组比较序列的最后一个数的位置
              for (int j = i; j < arr.length; j++) {
                  //根据该比较序列的最后一个数的位置,依次向前执行插入排序
                  for (int k = j-i; k >=0; k-=i) {
                      if(arr[k]>arr[k+i]){
                          temp = arr[k];
                          arr[k]  = arr[k+i];
                          arr[k+i] = temp;
                      }
                  }
              }
          }
      }
  }

第六种堆排序

package com.shuzu;
import java.util.Arrays;
/**
 * 堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就
 * 是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重
 * 新构造成一个堆,这样会得到n个元素的次小值。
 * 如此反复执行,便能得到一个有序序列了
 * @author MZFAITHDREAM
 *
 */
public class Sor28 {
   public static void main(String[] args) {
          int[] arr = new int[]{4,6,8,5,9};
          int length = arr.length;
          //从最后一个非叶节点开始构建大顶堆
          for (int i = arr.length/2-1; i >=0; i--) {
              maximumHeap(i,arr,length);
          }
          //从最小的叶子节点开始与根节点进行交换并重新构建大顶堆
          for (int i = arr.length-1; i >=0; i--) {
//              System.out.println(Arrays.toString(arr));
              swap(arr,0,i);
              length--;
              maximumHeap(0,arr,length);
          }
          System.out.println(Arrays.toString(arr));
      }
      //构建大顶堆
      public static void maximumHeap(int i,int[] arr,int length){
          int temp = arr[i];
          for (int j = i*2+1; j < length; j=j*2+1) {
              //如果右孩子大于做孩子,则指向右孩子
              if(j+1<length && arr[j+1]>arr[j]){
                  j++;
              }
              //如果最大的孩子大于当前节点,则将大孩子赋给当前节点,修改当前节点为其大孩子节点,再向下走。
              if(arr[j]>temp){
                  arr[i] = arr[j];
                  i = j;
              }else{
                  break;
              }
          }
          //将temp放到最终位置
          arr[i] = temp;
      }
      //交换
      public static void swap(int[] arr,int i,int j){
          int temp = arr[i];
          arr[i] = arr[j];
          arr[j] = temp;
      }
}

第7种方式基数排序。

package com.shuzu;
import java.util.Arrays;
public class sor3 {
  /**
   * 基数排序第i趟将待排数组里的每个数的i位数放到tempj(j=1-10)队列中,然后再从这十个队列中取出数据,重新放到原数组里,直到i大于待排数的最大位数。
1.数组里的数最大位数是n位,就需要排n趟,例如数组里最大的数是3位数,则需要排3趟。
2.若数组里共有m个数,则需要十个长度为m的数组tempj(j=0-9)用来暂存i位上数为j的数,例如,第1趟,各位数为0的会被分配到temp0数组里,各位数为1的会被分配到temp1数组里......
3.分配结束后,再依次从tempj数组中取出数据,遵循先进先进原则,例如对数组{1,11,2,44,4},进行第1趟分配后,temp1={1,11},temp2={2},temp4={44,4},依次取出元素后{1,11,2,44,4},第一趟结束
4.循环到n趟后结束,排序完成
1.  时间复杂度:
每一次关键字的桶分配都需要O(n)的时间复杂度,而且分配之后得到新的关键字序列又需要O(n)的时间复杂度。
假如待排数据可以分为d个关键字,则基数排序的时间复杂度将是O(d*2n) ,当然d要远远小于n,因此基本上还是线性级别的。
系数2可以省略,且无论数组是否有序,都需要从个位
   * @param args
   */
  public static void main(String[] args) {
    // TODO Auto-generated method stub
     int[] arr = new int[]{10,6,3,8,33,27,66,9,7,88};
          radixSort(arr);
      }
      private static void radixSort(int[] arr) {
          //求出待排数的最大数
          int maxLength=0;
          for (int i = 0; i < arr.length; i++) {
              if(maxLength<arr[i])
                  maxLength = arr[i];
          }
          //根据最大数求最大长度
          maxLength = (maxLength+"").length();
          //用于暂存数据的数组
          int[][] temp = new int[10][arr.length];
          //用于记录temp数组中每个桶内存的数据的数量
          int[] counts = new int[10];
          //用于记录每个数的i位数
          int num = 0;
          //用于取的元素需要放的位置
          int index = 0;
          //根据最大长度决定排序的次数
          for (int i = 0,n=1; i < maxLength; i++,n*=10) {
              for (int j = 0; j < arr.length; j++) {
                  num = arr[j]/n%10;
                  temp[num][counts[num]] = arr[j];
                  counts[num]++;
              }
              //从temp中取元素重新放到arr数组中
              for (int j = 0; j < counts.length; j++) {
                  for (int j2 = 0; j2 < counts[j]; j2++) {
                      arr[index] = temp[j][j2];
                      index++;
                  }
                  counts[j]=0;
              }
              index=0;
          }
          System.out.println(Arrays.toString(arr));
      }
  }

重点在思想上的领悟。

相关文章
|
20天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
12天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
54 8
|
12天前
|
搜索推荐 算法 C语言
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
43 7
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
【EMNLP2024】基于多轮课程学习的大语言模型蒸馏算法 TAPIR
阿里云人工智能平台 PAI 与复旦大学王鹏教授团队合作,在自然语言处理顶级会议 EMNLP 2024 上发表论文《Distilling Instruction-following Abilities of Large Language Models with Task-aware Curriculum Planning》。
|
20天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
20天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
27天前
|
算法 安全 数据安全/隐私保护
基于game-based算法的动态频谱访问matlab仿真
本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
|
12天前
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
13天前
|
算法 调度
基于遗传模拟退火混合优化算法的车间作业最优调度matlab仿真,输出甘特图
车间作业调度问题(JSSP)通过遗传算法(GA)和模拟退火算法(SA)优化多个作业在并行工作中心上的加工顺序和时间,以最小化总完成时间和机器闲置时间。MATLAB2022a版本运行测试,展示了有效性和可行性。核心程序采用作业列表表示法,结合遗传操作和模拟退火过程,提高算法性能。
|
14天前
|
存储 算法 决策智能
基于免疫算法的TSP问题求解matlab仿真
旅行商问题(TSP)是一个经典的组合优化问题,目标是寻找经过每个城市恰好一次并返回起点的最短回路。本文介绍了一种基于免疫算法(IA)的解决方案,该算法模拟生物免疫系统的运作机制,通过克隆选择、变异和免疫记忆等步骤,有效解决了TSP问题。程序使用MATLAB 2022a版本运行,展示了良好的优化效果。