非目录
- 缘起
- 代码地址
- 案例
- 桶排序
- 冒泡排序
- 快速排序
缘起
各位大哥大姐,兄弟姐妹们好呀!本人最近看了下《啊哈算法》,说来惭愧,买几年了,当初看了一会儿就吃灰了。
不过写的确实蛮好的,生动形象,精准有趣。
但稍显遗憾的是,书籍示例代码是c语言,不是本人常用的Java。
那就弥补遗憾,说干就干,把这本书的示例语言用java走一遍!!! 顺便附上自己的一些理解。
于是就有了本篇博客,本篇主要是通过一个具体案例,总结一下之前讲的三个排序算法:
Java玩转《啊哈算法》排序之桶排序
Java玩转《啊哈算法》排序之冒泡排序
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 号。
根据题目,我们不难得出,题目分为 去重、 排序和 计数 三步。那么这道题用三种排序算法要怎么做呢?
我们来分析一下:
- 如果是用桶排序的话,我们直接入桶的同时并计数,然后输出有元素的桶就好。
- 如果使用冒泡排序或者快速排序的话,需要先升序排序,然后再判断是否有重复的元素并计数。
话不多说,下面直接上代码,具体解释看代码注释就好了。
桶排序
核心代码:
/*** @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;}
}
启动程序,输入可得:
完美!!!