Java玩转《啊哈算法》排序综合篇之小哼买书

是诸法空相,不生不灭,不垢不净,不增不减

缘起

各位大哥大姐,兄弟姐妹们好呀!本人最近看了下《啊哈算法》,说来惭愧,买几年了,当初看了一会儿就吃灰了。

不过写的确实蛮好的,生动形象,精准有趣。

但稍显遗憾的是,书籍示例代码是c语言,不是本人常用的Java。

那就弥补遗憾,说干就干,把这本书的示例语言用java走一遍!!! 顺便附上自己的一些理解。

于是就有了本篇博客,本篇主要是通过一个具体案例,总结一下之前讲的三个排序算法:

  1. Java玩转《啊哈算法》排序之桶排序

  2. Java玩转《啊哈算法》排序之冒泡排序

  3. Java玩转《啊哈算法》排序之快速排序

在这里插入图片描述

来不及买纸质书但又想尽快感受算法魅力的童鞋也甭担心,电子版的下载链接已经放到下方了,可尽情下载。

链接:https://pan.baidu.com/s/1imxiElcCorw2F-HJEnB-PA?pwd=jmgs
提取码:jmgs

代码地址

本文代码已开源:

git clone https://gitee.com/guqueyue/my-blog-demo.git

请切换到gitee分支,

然后查看aHaAlgorithm模块下的src/main/java/com/guqueyue/aHaAlgorithm/chapter_1_Sort即可!

案例

按照本书,给出了一个案例:

小哼的学校要建立一个图书角,老师派小哼去找一些同学做调查,看看同学们都喜欢读哪些书。小哼让每个同学写出一个自己最想读的书的ISBN号(你知道吗?每本书都有唯一的ISBN号,不信的话你去找本书翻到背面看看)。当然有一些好书会有很多同学都喜欢,这样就会收集到很多重复的ISBN号。小哼需要去掉其中重复的ISBN号,即每个ISBN号只保留一个,也就说同样的书只买一本(学校真是够抠门的)。然后再把这些ISBN号从小到大排序,小哼将按照排序好的ISBN号去书店买书。请你协助小哼完成 “去重” 与 “排序” 的工作。

在这里插入图片描述

当然,我们这里为了方便,做一下输入限制:

输入有2行,
第1行为一个正整数,表示有n个同学参与调查(n≤100)。
第2行有n 个用空格隔开的正整数,为每本图书的ISBN号(假设图书的ISBN号在1~1000之间)。

然后我们需要输出:

输出也是 2 行,
第 1 行为一个正整数 k,表示需要买多少本书。
第 2 行为 k 个用空格隔开的正整数,为从小到大已排好序的需要购买的图书的 ISBN 号。

根据题目,我们不难得出,题目分为 去重排序计数 三步。那么这道题用三种排序算法要怎么做呢?

我们来分析一下:

  1. 如果是用桶排序的话,我们直接入桶的同时并计数,然后输出有元素的桶就好。
  2. 如果使用冒泡排序或者快速排序的话,需要先升序排序,然后再判断是否有重复的元素并计数。

话不多说,下面直接上代码,具体解释看代码注释就好了。

桶排序

核心代码:

 	/**
     * @Description 桶排序 - 去重
     * @Param [arr: 待去重排序后的数组]
     * @return
     **/
    private static void bucketSort(int[] arr) {

        int count = 0; // 声明变量,用于计数

        int[] bucket = new int[1001];
        for (int i : arr) { // 遍历数组

            if(bucket[i] == 0) { // 计数
                count++;
            }

            bucket[i]++; // 入桶
        }

        System.out.println("需要买书的本数为: " + count);
        System.out.print("得到去重排序后的ISBN号数组为: ");
        for (int i = 0; i < 1001; i++) { // 遍历桶
            if (bucket[i] > 0) { // 桶内有数,则输出桶
                System.out.print(i + " ");
            }
        }
        // 换行
        System.out.println();
    }

完整代码:

package com.guqueyue.aHaAlgorithm.chapter_1_Sort;

import java.util.Scanner;

/**
 * @Author: guqueyue
 * @Description: 小哼买书,去书籍的ISBN号进行去重排序
 * @Date: 2024/1/10
 **/
public class BuyBook {
    public static void main(String[] args) {

        // 获取书籍的ISBN号
        int[] arr = getArr();

        // 桶排序
        bucketSort(arr);
    }

    /**
     * @Description 桶排序 - 去重
     * @Param [arr: 待去重排序后的数组]
     * @return
     **/
    private static void bucketSort(int[] arr) {

        int count = 0; // 声明变量,用于计数

        int[] bucket = new int[1001];
        for (int i : arr) { // 遍历数组

            if(bucket[i] == 0) { // 计数
                count++;
            }

            bucket[i]++; // 入桶
        }

        System.out.println("需要买书的本数为: " + count);
        System.out.print("得到去重排序后的ISBN号数组为: ");
        for (int i = 0; i < 1001; i++) { // 遍历桶
            if (bucket[i] > 0) { // 桶内有数,则输出桶
                System.out.print(i + " ");
            }
        }
        // 换行
        System.out.println();
    }

    /**
     * @Description 获取书籍的ISBN号
     * @Param []
     * @return int[]
     **/
    private static int[] getArr() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入书籍数: ");
        int n = scanner.nextInt();

        int[] arr = new int[n];
        System.out.printf("请输入第%d本书的ISBN号(0-1000), 中间用空格隔开,再回车:", n);
        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }
        return arr;
    }
}

演示:
在这里插入图片描述

大功告成!

冒泡排序

冒泡排序跟桶排序不同的是,它是先排序,再进行去重和计数

而其中排序的代码跟之前的博客的内容别无二致,但是需要增加去重和计数的代码:

 		// 去重计数
        int count = 1;
        String str = arr[0] + " "; // 保存第一个数
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] != arr[i-1]) { // 与前一个不相等则存起来方便输出
                str += arr[i] + " ";

                count++; // 计数
            }
        }

        // 输出
        System.out.println("需要买书的本数为: " + count);
        System.out.println("得到去重排序后的ISBN号数组为: " + str);

完整代码:

package com.guqueyue.aHaAlgorithm.chapter_1_Sort;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @Author: guqueyue
 * @Description: 小哼买书,去书籍的ISBN号进行去重排序 - 冒泡排序
 * @Date: 2024/1/10
 **/
public class BuyBook2 {
    public static void main(String[] args) {

        // 获取书籍的ISBN号
        int[] arr = getArr();

        // 冒泡排序
        bubbleSort(arr);
        System.out.println("得到排序后的ISBN号数组为: " + Arrays.toString(arr));

        // 去重计数
        int count = 1;
        String str = arr[0] + " "; // 保存第一个数
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] != arr[i-1]) { // 与前一个不相等则存起来方便输出
                str += arr[i] + " ";

                count++; // 计数
            }
        }

        // 输出
        System.out.println("需要买书的本数为: " + count);
        System.out.println("得到去重排序后的ISBN号数组为: " + str);
    }

    /**
     * @Description 冒泡排序 
     * @Param [arr]
     * @return int[]
     **/
    private static void bubbleSort(int[] arr) {

        int n = arr.length;
        for (int i = 0; i < n - 1; i++) { // 交换
            for (int j = 1; j < n-i; j++) {
                if (arr[j] < arr[j-1]) {
                    int t = arr[j]; arr[j] = arr[j-1]; arr[j-1] = t;
                }
            }
        }
    }


    /**
     * @Description 获取书籍的ISBN号
     * @Param []
     * @return int[]
     **/
    private static int[] getArr() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入书籍数: ");
        int n = scanner.nextInt();

        int[] arr = new int[n];
        System.out.printf("请输入第%d本书的ISBN号(0-1000), 中间用空格隔开,再回车:", n);
        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }
        return arr;
    }
}

运行代码,控制台输入,可得:

在这里插入图片描述

快速排序

快速排序跟冒泡排序类似,都是先排序,再进行去重和计数,无非是排序的算法发生了变化:

package com.guqueyue.aHaAlgorithm.chapter_1_Sort;

import java.util.Arrays;
import java.util.Scanner;

/**
 * @Author: guqueyue
 * @Description: 小哼买书,去书籍的ISBN号进行去重排序 - 快速排序
 * @Date: 2024/1/10
 **/
public class BuyBook3 {
    public static void main(String[] args) {

        // 获取书籍的ISBN号
        int[] arr = getArr();

        // 快速排序
        quickSort(arr, 0, arr.length-1);
        System.out.println("得到排序后的ISBN号数组为: " + Arrays.toString(arr));

        // 去重计数
        int count = 1;
        String str = arr[0] + " "; // 保存第一个数
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] != arr[i-1]) { // 与前一个不相等则存起来方便输出
                str += arr[i] + " ";

                count++; // 计数
            }
        }

        // 输出
        System.out.println("需要买书的本数为: " + count);
        System.out.println("得到去重排序后的ISBN号数组为: " + str);
    }

    /**
     * @Description 快速排序
     * @Param [arr, left, right]
     * @return void
     **/
    private static void quickSort(int[] arr, int left, int right) {

        if (left >= right) {
            return;
        }

        int i = left, j = right, temp = arr[left]; // temp为基准值
        while (i < j) { // 相遇了就不能继续找了

            // 右边的先找
            while (arr[j] >= temp && i < j) {
                j--;
            }

            // 左边的后找
            while (arr[i] <= temp && i < j) {
                i++;
            }

            // 如果没有相遇,则交换
            if (i < j) {
                int t = arr[i];
                arr[i] = arr[j];
                arr[j] = t;
            }
        }

        // 交换基准值
        arr[left] = arr[i];
        arr[i] = temp;

        // 继续左边找
        quickSort(arr, left, i-1);

        // 继续右边找
        quickSort(arr, i+1, right);
    }


    /**
     * @Description 获取书籍的ISBN号
     * @Param []
     * @return int[]
     **/
    private static int[] getArr() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("请输入书籍数: ");
        int n = scanner.nextInt();

        int[] arr = new int[n];
        System.out.printf("请输入第%d本书的ISBN号(0-1000), 中间用空格隔开,再回车:", n);
        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }
        return arr;
    }
}

启动程序,输入可得:

在这里插入图片描述
完美!!!

  • 33
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值