当前位置: 首页 > news >正文

详解:递归 和 排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,希尔排序)

一、 递归

一个调用它本身的函数称为递归(Recursive)函数。在编写程序时,也常来处理某些问题,而这些问题通常有相同的规则,下面将举例说明。
n 阶乘
n!=n ×(n-1)!
(n-1)!=(n-1)×(n-2)!
(n-2)!=(n-2)×(n-3)!

1!=1
从上述公式可得知其相同的规则为:某一数A的阶乘为本身A乘以(A-1)的阶乘。其程序如下:

public int fun(int n){
	int a;
	if(n==1)
	a=1else 
	a=n * fun (n-1);
	return a;
	}

在编写递归程序时,记住必须有一个结束点,可以使函数往上追溯直到结束。如上例中,当 n= 1 时,1!= 1 即为其结束点。
程序解说
下图表示n!阶乘,假设n=4,如图
在这里插入图片描述

二、 排序

(冒泡排序,选择排序,插入排序,归并排序,快速排序,希尔排序)

1、冒泡排序:
冒泡排序(Bubble Sont)又称为交换排序(Interchange Sont)。相邻两个相比,如果前一个比后一个大时,则互相对调。通常有 n 个数据时需要做n+1次扫描,一次扫描完后,数据量减少 1,当没有数据需要对调时,就表示已好排好序了。
例如,有 5 个数据分别是20,2,25,56,15 冒泡排序的步骤如下;
在这里插入图片描述冒泡排序一样是稳定的,最坏时间与平均时间都是 O(n²),所需要额外空间也很少。
代码解释:

public class test {
    public static void main(String[] args) {
        int a[]={20,2,25,56,15};
        talk(a);
    }
    public static void talk(int a[]){
        p(a);//打印出原来的数组顺序
        int i,j,temp;
        //让数据两两作对比,将小的置于前
        for( i=0;i<a.length;i++){
            int flag=0;//退出冒泡循环的标志
            for (j = 0; j < a.length-i-1; j++) {
                if (a[j] > a[j+1]){
                    temp=a[j+1];
                    a[j+1]=a[j];
                    a[j]=temp;
                    flag=1;
                    p(a);
                }
            }
            if(flag != 1)  { 
                break;
            }
        }
    }
    /*打印数组方法*/
    private static void p(int a[]){
        for(int i : a){
            System.out.print(i+" ");
        }
        System.out.println();
    }
}

结果:
20 2 25 56 15
2 20 25 56 15
2 20 25 15 56
2 20 15 25 56
2 15 20 25 56

2、选择排序
选择排序(Selection Sort)首先在所有的数据中挑选一个最小的放在第一个位置由小到大排序),再从第二个开始挑选一个最小的放于第二个位置,以此类推。假设有n个记录,则最多需要 n-1 次对调,以及n(n-1)2次比较。
例如,有 5 个记录,为 16,4,20,35,15。利用选择排序,其做法如下:在这里插入图片描述选择排序跟冒泡排序一样是稳定的,最坏时间与平均时间都是 O(n²),所需要额外空间也很少。

代码解释:

public class test2 {
    public static void main(String[] args) {
        int a[]={16,4,20,35,15};
        talk(a);
    }
    public static void talk(int a[]){
        int min,temp;
        for (int i = 0; i < a.length-1; i++) {
            min=i;
            for (int j = i+1; j < a.length; j++) {
                if (a[j] < a[min]) {
                    min = j;
                }
            }
            if (i != min) {
                temp = a[i];
                a[i] = a[min];
                a[min] = temp;
            }
            p(a);
        }
    }

    private static void p(int a[]){
        for (int i : a){
            System.out.print(i+" ");
        }
        System.out.println();
    }
}

结果:
4 16 20 35 15
4 15 20 35 16
4 15 16 35 20
4 15 16 20 35

3、插入排序
插入排序(Insertion Sort)是将插入的数据置于原来的文件适当的位置,如下图:
在这里插入图片描述插入排序是稳定的,最坏的时间与平均时间为O(n²),所需的额外空间少。
代码解释:

4、归并排序
归并排序(Merge Sont)是将两个或两个以上已排序好的文件,合并成一个大的已排序好的文件。
例如,有两个已排序好的文件分别为
甲= {4, 8, 12, 16, 25}
乙= {6, 10, 15,35, 40}
归并排序过程如下:甲文件的第一个数据是4,而乙第一个数据是6,由于4小于6,故将4写入两文件的第一个数据;甲文件的第二个数据是8,8 比6 大,故 6写入丙文件;乙文件的第二个数据为10,12比10大。故10写入丙文件:以此类推,最后丙文件为{4,6,8,10,12,15,16,25,35,40}。

5、快速排序
快速排序(Quick Sont)又称为划分交换排序(Parition Bxchange Sorig),就平的时间而言,快速排序是所有排序中最佳的。假设有 n个 R1, R2,R3,…R,其关键字为K1,K2,以.…,Kn。快速排序法的步骤如下:

  1. 以第一个记录的关键字 k1 做基准 K。
  2. 由左至右i=2,3,…,n,一直找到ki > K.
  3. 由右至左j= n, n-1,n-2,…,2,一直找到kj≤ K。
  4. 当i<j时 Ri与 Rj 互换,否则 R1 与Rj互换。
    在这里插入图片描述由图可以看出39左边都是比39小的,右边是比39大的,所以继续用上述方法即可(形成递归)

6、希尔排序
希尔排序(Shell’s Sort)是插入排序的一种又称“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。
希尔排序方法:
(1)先将所有的数据分成Y=(9 Div 2)部分Y=4,Y 为划分数。
(2)每个循环的划分数是 Y,都是上一循环二分数除 2,即 Yi= Yi Div 2,逐渐缩小的增量组成一个序列: [n/2, n/2/2, … 1],最后一个循环的划分数为1,当增量等于 1 时,排序整个数组后,排序完成。

public class rc {
    public static void main(String[] args) {
        int a[]= {10, 22, 18, 45, 25, 75, 64, 45, 99};
        talk(a);
    }
    private static void talk(int[] a) {
        int step = a.length / 2; //步长,默认取数组长度一半
        int temp;
        while (step > 0) {
            for (int i = step; i <a.length; i++) {
                temp = a[i];//当前值
                int preIndex = i - step; //步长间隔上一个值的下标
              //在步长间隔的的数组中,找到需要插入的位置,挪动右边的数
                while (preIndex >= 0 && a[preIndex] > temp) {
                    a[preIndex + step] = a[preIndex];
                    preIndex -= step;
                }
                //把当前值插入到在步长间隔的的数组中找到的位置
                a[preIndex + step] = temp;
            }
            step /= 2;
            p(a);
        }
    }
    private static void p(int[] a) {
        for(int i : a) {
            System.out.print(i + " ");
        }
        System.out.println();
    }

}

结果:
10 22 18 45 25 75 64 45 99
10 22 18 45 25 45 64 75 99
10 18 22 25 45 45 64 75 99

相关文章:

  • postgresql-patroni高可用安装部署
  • Linux使用Clash,clash-for-linux
  • P2847 [USACO16DEC] Moocast G
  • MySQL —— 视图
  • self-play RL学习笔记
  • Rabbitmq中得RPC调用代码详解
  • xss.haozi.me靶场练习
  • Java Web(十一)--JSON Ajax
  • 【大数据】Flink SQL 语法篇(九):Window TopN、Deduplication
  • uniapp的动态表单实现
  • Spring Boot基础面试问题(一)
  • 主数据管理是数字化转型成功的基石——江淮汽车案例分享
  • 【问题记录】防止mimikatz获取到明文密码
  • 超实用的JS常用算法详解(推荐)
  • 02-nginx环境准备
  • CSS 基础知识 属性
  • 【学生管理系统】整合JWT(完)
  • maya2023 安装和导入PyMEL
  • Java学习--JDBC
  • 【HDU No. 1224】 免费DIY之旅
  • 中国软件三季度业绩预测,中国软件股票趋势预测
  • 【MATLAB教程案例26】图像特征点提取算法matlab仿真与分析——sift,surf,kaze,corner,BRISK等
  • Tinyhttpd -- 用 C 从零写一个 HTTP 服务器
  • 计算机网络--应用层(https)
  • LeetCode每日一题——902. 最大为 N 的数字组合
  • 【上传图片,文件,视频功能合集】vue-elementul简单实现上传文件,上传图片,上传视频功能【详细注释,简单易用】
  • 大学四年庸庸碌碌,我弯道超车上了软件测试
  • 信安软考 第十八章 网络安全测评技术与标准
  • 粒子群算法PSO求解最大值和最小值案例(超详细注释)
  • ArrayList和CopyOnWriteArrayList
  • Java中的JDK动态代理
  • 基于Springboot实现留守儿童管理系统