2843 字
14 分钟
从零开始编写数字处理程序:一个Java小白的完整指南
本文将带你一步步实现一个功能完整的数字处理程序,涵盖输入处理、排序算法、去重操作和单调栈应用。即使你是Java新手,也能跟着这个指南完成编码。
程序概述
我们要编写的程序能够:
- 自动检测系统语言(中英文)
- 处理用户输入的数字
- 随机选择排序算法进行排序
- 去除重复数字
- 使用单调栈进行特殊处理
- 提供动画效果的执行过程
第一步:搭建基础框架
// 定义入口点:main 是 Java 程序启始位void main() { // 主逻辑占位:此处待实现功能 // 当前空,表未写具体代}
// 睡函 - 造延效果// 入参:milliseconds - 线程停多长(毫秒)void sleep(int milliseconds) { try { // 调 Thread.sleep,让当线程休指时长 Thread.sleep(milliseconds); } catch (InterruptedException e) { // 若线程睡中被断,则恢其断状 Thread.currentThread().interrupt(); }}
// 打印数组 - 以 [a,b,c] 格式输到控台// 入参:arr - 要打的 int 型数组void printArray(int[] arr) { System.out.print("["); // 先打左括,表数组开 for (int i = 0; i < arr.length; i++) { // 遍数每元 System.out.print(arr[i]); // 打当元 if (i < arr.length - 1) { // 判是为最一元 System.out.print(","); // 非末则加逗隔 } } System.out.println("]"); // 打右括并换行,表数组束}代码解释:
main()函数是程序入口点sleep()函数让程序暂停指定毫秒,创造动画效果printArray()函数以美观格式输出数组
第二步:实现语言检测和输入处理
void main() { // 取系统语种(如:zh=中文,en=英文) String language = System.getProperty("user.language"); // 判是否为中文环:zh 或 cn 即视为中 boolean isChinese = "zh".equals(language) || "cn".equals(language);
// 按语种显对应提语 String input = readInput(isChinese ? "请输入数字: " : "Enter numbers: ");
// 抽字串中所数,转为整数数 int[] numbers = extractSingleDigits(input);
// 原样打数组(带[ ]格式) printArray(numbers); // 停300毫秒,造延缓效 sleep(300);}
// 读用户输的一行文// 入参:prompt - 提示语(中or英)// 出参:用户输内(错时为空串)String readInput(String prompt) { // 显提语不换行 System.out.print(prompt);
try { // 建读器,用读键输 java.io.BufferedReader reader = new java.io.BufferedReader( new java.io.InputStreamReader(System.in)); // 读一整并回 return reader.readLine(); } catch (Exception e) { // 出错(如IO异常)则回空串 return ""; }}
// 抽字串中所单数,转为int数组// 入参:input - 原始输字串// 出参:只含数的整型数组int[] extractSingleDigits(String input) { int count = 0; // 记数个数
// 一遍历:数有几数 for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); // 取当字 if (c >= '0' && c <= '9') { // 是0-9间? count++; // 是则计+1 } }
// 新数组,长=数个数 int[] numbers = new int[count]; int index = 0; // 数组写位指针
// 二遍历:数抽整存数组 for (int i = 0; i < input.length(); i++) { char c = input.charAt(i); // 取当字 if (c >= '0' && c <= '9') { // 是数? numbers[index++] = c - '0'; // 转整存,指针++ } }
// 回抽完的数数组 return numbers;}代码解释:
- 使用
System.getProperty("user.language")检测系统语言 readInput()读取用户输入,支持中英文提示extractSingleDigits()从字符串中提取数字字符并转换为整数
第三步:实现排序算法
// 随机选一排序法// 出参:返回一个排序算名(如“冒泡排序”)String selectRandomSort() { // 定义支持的四种排序法 String[] sorts = {"冒泡排序", "快速排序", "选择排序", "归并排序"}; // 用当前时间毫秒取模4,得0-3的索引 int index = (int)(System.currentTimeMillis() % 4); // 返回随机选中的排序法名 return sorts[index];}
// 按指定排序法对数列排序// 入参:numbers - 原数组;sortType - 排序类名// 出参:已排序的新数组int[] sortNumbers(int[] numbers, String sortType) { // 克隆原数组,避免修改原数据 int[] sorted = numbers.clone();
// 根据排序类名调对应算法 switch (sortType) { case "冒泡排序": bubbleSort(sorted); // 调冒泡 break; case "快速排序": quickSort(sorted, 0, sorted.length - 1); // 调快排 break; case "选择排序": selectionSort(sorted); // 调选排 break; case "归并排序": // 归并返新数组,需重赋值 sorted = mergeSort(sorted); break; }
// 回排完的数 return sorted;}
// 冒泡排序:相临比,大者后移// 入参:arr - 待排数组(直改原数组)void bubbleSort(int[] arr) { int n = arr.length; // 数长 for (int i = 0; i < n - 1; i++) { // 控制趟数 for (int j = 0; j < n - i - 1; j++) { // 每趟比前n-i-1个 if (arr[j] > arr[j + 1]) { // 前>后则交 int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } }}
// 快速排序:分治法,选基,小左大右// 入参:arr - 数组;low - 起位;high - 终位void quickSort(int[] arr, int low, int high) { if (low < high) { // 至少两元才需排 int pi = partition(arr, low, high); // 分区得基位 quickSort(arr, low, pi - 1); // 排左区 quickSort(arr, pi + 1, high); // 排右区 }}
// 分区操作:将数组按基分两部// 入参:arr, low, high// 出参:基元素最终位int partition(int[] arr, int low, int high) { int pivot = arr[high]; // 取最末为基 int i = low - 1; // 小于区的边界指针
for (int j = low; j < high; j++) { // 遍除基外所元 if (arr[j] <= pivot) { // 当元≤基 i++; // 扩小分区 // 交arr[i]与arr[j] int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } }
// 交基(arr[high])与i+1位元 int temp = arr[i + 1]; arr[i + 1] = arr[high]; arr[high] = temp;
return i + 1; // 回基位}
// 选择排序:每轮选最,放当位// 入参:arr - 待排数组void selectionSort(int[] arr) { int n = arr.length; for (int i = 0; i < n - 1; i++) { // 控制选位 int minIdx = i; // 假设当元最 for (int j = i + 1; j < n; j++) { // 遍后所元 if (arr[j] < arr[minIdx]) { // 找更小的 minIdx = j; // 记其索引 } } // 交arr[i]与最元 int temp = arr[minIdx]; arr[minIdx] = arr[i]; arr[i] = temp; }}
// 归并排序:分而治之,递归拆合// 入参:arr - 原数组// 出参:新排数组int[] mergeSort(int[] arr) { if (arr.length <= 1) { // 基线:长≤1直回 return arr; }
int mid = arr.length / 2; // 找中点 int[] left = new int[mid]; // 左半 int[] right = new int[arr.length - mid]; // 右半
// 拷数到左右子组 for (int i = 0; i < mid; i++) { left[i] = arr[i]; } for (int i = mid; i < arr.length; i++) { right[i - mid] = arr[i]; }
// 递归排左右 left = mergeSort(left); right = mergeSort(right);
// 合并两有序子组 return merge(left, right);}
// 合并:将两个有序数组合为一个有序数组// 入参:left, right - 两个有序子数组// 出参:合并后的有序大数组int[] merge(int[] left, int[] right) { // 新数组长=左长+右长 int[] result = new int[left.length + right.length]; int i = 0, j = 0, k = 0; // 三指针:左、右、结果
// 同有数时,取小者入结 while (i < left.length && j < right.length) { if (left[i] <= right[j]) { result[k++] = left[i++]; } else { result[k++] = right[j++]; } }
// 处左剩 while (i < left.length) { result[k++] = left[i++]; }
// 处右剩 while (j < right.length) { result[k++] = right[j++]; }
// 回合完的有数 return result;}排序算法要点:
- 冒泡排序:相邻元素比较交换,简单但效率低
- 快速排序:分治思想,选择基准元素分区
- 选择排序:每次选择最小元素放到前面
- 归并排序:分治思想,合并有序子数组
第四步:实现去重功能
// 获取唯一数字(去重)int[] getUniqueNumbers(int[] numbers) { if (numbers.length == 0) return new int[0];
// 先计算唯一数字的数量 int uniqueCount = 1; for (int i = 1; i < numbers.length; i++) { if (numbers[i] != numbers[i - 1]) { uniqueCount++; } }
// 创建结果数组 int[] unique = new int[uniqueCount]; unique[0] = numbers[0]; int index = 1;
for (int i = 1; i < numbers.length; i++) { if (numbers[i] != numbers[i - 1]) { unique[index++] = numbers[i]; } }
return unique;}去重逻辑:
- 前提:数组必须已排序
- 遍历数组,只保留与前一个元素不同的元素
第五步:实现单调栈处理
// 用单调栈处数,并打每步// 入参:numbers - 数列;isChinese - 是否中提void processWithMonotonicStack(int[] numbers, boolean isChinese) { if (numbers.length == 0) return; // 空则直退
// 用数组模栈结:stack 数组 + top 指针 int[] stack = new int[numbers.length]; // 栈存数 int top = -1; // 栈顶指针(-1 = 空)
// 入栈序:保栈单递增(从底到顶) for (int num : numbers) { // 遍每数 // 弹所小栈顶:保单性 while (top >= 0 && stack[top] < num) { if (isChinese) { System.out.println(stack[top] + " 已出栈!"); } else { System.out.println(stack[top] + " popped!"); } sleep(200); // 停0.2秒,造动效 top--; // 出栈:指针减1 }
// 当数入栈 stack[++top] = num; // 先+1,再赋值 if (isChinese) { System.out.println(num + " 已进栈!"); } else { System.out.println(num + " pushed!"); } sleep(200); // 停0.2秒 }
// 完提 if (isChinese) { System.out.println("完成!"); System.out.println("======================="); } else { System.out.println("Completed!"); System.out.println("======================="); }}
// 出栈流:模后进先出(LIFO)// 入参:numbers - 原数组(视为栈中数)// 出参:出栈顺的新数组int[] popFromStack(int[] numbers, boolean isChinese) { // 栈为LIFO,故出栈序 = 原序逆 int[] result = new int[numbers.length]; for (int i = 0; i < numbers.length; i++) { // 从尾到头取数 result[i] = numbers[numbers.length - 1 - i]; if (isChinese) { System.out.println(result[i] + " 已出栈!"); } else { System.out.println(result[i] + " popped!"); } sleep(200); // 每出一停0.2秒 } return result; // 回出栈序}单调栈概念:
- 保持栈内元素单调递增或递减
- 用于解决”下一个更大元素”等问题
- 这里实现的是递增栈
第六步:整合完整的主函数
void main() { // 检测系统语言 String language = System.getProperty("user.language"); boolean isChinese = "zh".equals(language) || "cn".equals(language);
// 读取输入 String input = readInput(isChinese ? "请输入数字: " : "Enter numbers: ");
// 提取每个单独的数字字符 int[] numbers = extractSingleDigits(input);
// 原样输出 printArray(numbers); sleep(300);
// 随机选择排序算法 String sortType = selectRandomSort(); if (isChinese) { System.out.println("当前自动选择:" + sortType); } else { System.out.println("Currently selected: " + sortType); } sleep(500);
int[] sorted = sortNumbers(numbers, sortType); printArray(sorted); sleep(200);
// 唯一性处理 if (isChinese) { System.out.println("唯一性处理,启动!"); } else { System.out.println("Unique processing, starting!"); } sleep(100);
int[] unique = getUniqueNumbers(sorted); printArray(unique);
// 单调栈处理 if (isChinese) { System.out.println("进栈!"); } else { System.out.println("Pushing to stack!"); }
processWithMonotonicStack(unique, isChinese);
sleep(500);
if (isChinese) { System.out.println("出栈!"); } else { System.out.println("Popping from stack!"); }
// 出栈流程 int[] stackResult = popFromStack(unique, isChinese);
if (isChinese) { System.out.println("出栈完成!"); System.out.println("入表!"); } else { System.out.println("Popping completed!"); System.out.println("Adding to table!"); }
printArray(stackResult);
if (isChinese) { System.out.println("工作完成!"); System.out.println("======================="); sleep(500); System.out.println("tips:本示范来自blog.meowhead.cn,建议jdk版本24,盗文章死马。"); System.out.println("微信公众号:绪方小原"); } else { System.out.println("Work completed!"); System.out.println("======================="); sleep(500); System.out.println("tips: This demo is from blog.meowhead.cn, recommended JDK version 24."); System.out.println("WeChat public account: 绪方小原"); }}学习建议
- 分步调试:先实现基础功能,再逐步添加复杂功能
- 理解算法:重点理解每种排序算法的原理和优缺点
- 代码复用:学会将常用功能封装成函数
- 错误处理:在实际项目中要添加更多异常处理
运行示例
请输入数字: 7744233336899641024[7,7,4,4,2,3,3,3,3,6,8,9,9,6,4,1,0,2,4]当前自动选择:快速排序[0,1,2,2,3,3,3,3,4,4,4,4,6,6,7,7,8,9,9]唯一性处理,启动![0,1,2,3,4,6,7,8,9]进栈!0 已进栈!0 已出栈!1 已进栈!1 已出栈!2 已进栈!2 已出栈!3 已进栈!3 已出栈!4 已进栈!4 已出栈!6 已进栈!6 已出栈!7 已进栈!7 已出栈!8 已进栈!8 已出栈!9 已进栈!完成!=======================出栈!9 已出栈!8 已出栈!7 已出栈!6 已出栈!4 已出栈!3 已出栈!2 已出栈!1 已出栈!0 已出栈!出栈完成!入表![9,8,7,6,4,3,2,1,0]工作完成!=======================tips:本示范来自blog.meowhead.cn,建议jdk版本24,盗文章死马。微信公众号:绪方小原支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!
从零开始编写数字处理程序:一个Java小白的完整指南
https://blog.meowhead.cn/posts/d4f830a5-8eda-4a10-a5ca-b10122f3c6fe/ 最后更新于 2025-10-07,距今已过 129 天
部分内容可能已过时