排序算法
2014-12-15 12:58 雪夜&流星 阅读(188) 评论(0) 编辑 收藏 举报各种排序算法的实现:
package com.clarck.datastructure.array; /** * 排序 * * @author clarck * */ public class Array { /** * 输出数组元素 * @param table */ public static void print(int[] table) { if (table != null) { for (int i = 0; i < table.length; i++) { System.out.print(" " + table[i]); } System.out.println(); } } /** * 输出对象数组元素 * @param table */ public static void print(Object[] table) { if (table != null) { for (int i = 0; i < table.length; i++) { System.out.print(" " + table[i].toString()); } System.out.println(); } } /** * 直接插入排序,数组是引用类型,作为方法的参数,其元素值将被改变 * @param table */ public static void insertSort(int[] table) { System.out.println("直接插入排序"); //n - 1趟扫描 for (int i = 1; i < table.length; i++) { //每趟将table[i]插入到前面排序序列中 int temp = table[i], j; //将签名较大元素向后移动 for (j = i - 1; j >= 0 && temp < table[j]; j--) { table[i + 1] = table[j]; } //temp值到达插入位置 table[j + 1] = temp; System.out.print("第" + i + "趟: "); //输出排序中间结果,可省略 print(table); } } /** * 希尔排序 * @param table */ public static void shellSort(int[] table) { System.out.println("希尔排序"); //若干趟扫描,控制增量,增量减半 for (int delta = table.length / 2; delta > 0; delta /= 2) { //一趟分若干组,每组进行直接插入排序 for (int i = delta; i < table.length; i++) { //table[i] 是当前待插入元素 int temp = table[i], j; //每组元素相距delta远,寻找插入位置 for (j = i - delta; j > 0 && temp < table[j]; j-=delta) { table[j + delta] = table[j]; } table[j + delta] = temp; } System.out.print("delta=" + delta + " "); print(table); } } /** * 冒泡排序 * @param table */ public static void bubbleSort(int[] table) { System.out.println("冒泡排序"); //是否交换的标记 boolean exchange = true; //有交换是再进行下一趟,最多n-1趟 for (int i = 1; i < table.length && exchange; i++) { //假定元素未交换 exchange = false; //一趟比较、交换 for (int j = 0; j < table.length - i; j++) { if (table[j] > table[j + 1]) { int temp = table[j]; table[j] = table[j + 1]; table[j + 1] = temp; //有交换 exchange = true; } } System.out.print("第" + i + "趟:"); print(table); } } /** * 快速排序 * @param table */ public static void quickSort(int[] table) { System.out.println("快速排序"); quickSort(table, 0, table.length - 1); } /** * 一趟快速排序,begin、high指定序列的下界和上界,递归算法 * @param table * @param begin * @param end */ private static void quickSort(int[] table, int begin, int end) { //序列有效 if (begin < end) { int i = begin, j = end; //第一个值作为基准值 int vot = table[i]; //一趟排序 while (i != j) { //从后向前寻找较小值 while (i < j && vot <= table[j]) { j --; } if (i < j) { //较小元素向前移动 table[i++] = table[j]; } //从前向后寻找较大值 while (i < j && table[i] <= vot) { i++; } if (i < j) { //较大元素向后移 table[j--] = table[i]; } } //基准值到达最终位置 table[i] = vot; System.out.print(begin + ".." + end + ", vot=" + vot + " "); print(table); //前端子序列再排序,递归调用 quickSort(table, begin, j - 1); //后端子序列再排序,递归调用 quickSort(table, i + 1, end); } } /** * 直接选择排序 * @param table */ public static void selectSort(int[] table) { System.out.println("直接选择排序"); //n - 1趟排序 //每趟在从i开始的子序列中寻找最小元素 for (int i = 0; i < table.length - 1; i ++) { //设第i个数据元素最小 int min = 1; for (int j = i + 1; j < table.length; j++) { //记住最小元素下标 if (table[j] < table[min]) { min = j; } } //将本趟最小元素交换到前面 if (min != i) { int temp = table[i]; table[i] = table[min]; table[min] = temp; } System.out.print("第" + (i + 1) + "趟: "); print(table); } } /** * 堆排序(降序),最小堆 * @param table */ public static void heapSort_min(int[] table) { System.out.println("最小堆?" + isMinHeap(table)); System.out.println("建立最小堆序列"); int n = table.length; for (int j = n / 2 - 1; j >= 0; j++) { sift_min(table, j, n - 1); } System.out.println("最小堆?" + isMinHeap(table)); System.out.println("堆排序(降序)"); //每趟将最小值交换到后面,再调整成堆 for (int j = n - 1; j > 0; j--) { int temp = table[0]; table[0] = table[j]; table[j] = temp; sift_min(table, 0, j - 1); } } /** * 将以begin为根的子树调整成最小堆,begin、end是序列下界和上界 * @param table * @param j * @param i */ private static void sift_min(int[] table, int begin, int end) { //i为子树的根,j为i结点的左孩子 int i = begin, j = 2 * i + 1; //获得第i个元素的值 int temp = table[i]; //沿较小值孩子结点向下筛选 while (j <= end) { //数组元素比较(改成<为最大堆) if (j < end && table[j] > table[j + 1]) { //j为左右孩子的较小者 j ++; } //若父母结点值较大(改成<为最大堆) if (temp > table[j]) { //孩子结点中的较小值上移 table[i] = table[j]; i = j; j = 2 * j + 1; } else { break; } } //当前子树的原根值调整后的位置 table[i] = temp; System.out.print("sift " + begin + ".." + end + " "); print(table); } /** * 堆排序(升序),最大堆 * @param table */ public static void heapSort_max(int[] table) { System.out.println("最大堆?" + isMaxHeap(table)); System.out.println("建立最大堆序列"); int n = table.length; for (int j = n / 2 - 1; j >= 0; j--) { sift_max(table, j, n - 1); } System.out.println("最大堆?" + isMaxHeap(table)); System.out.println("堆排序(升序)"); //每趟将最大值交换到后面,再调整成堆 for (int j = n - 1; j > 0; j --) { int temp = table[0]; table[0] = table[j]; table[j] = temp; sift_max(table, 0, j - 1); } } /** * 将以begin为根的子树调整成最大堆,begin、end是序列下界和上界 * @param table * @param begin * @param end */ private static void sift_max(int[] table, int begin, int end) { //i为子树的根,j为i结点的左孩子 int i = begin, j = 2 * i + 1; //获得第i个元素的值 int temp = table[i]; //沿较大值孩子结点向下筛选 while (j <= end) { //数组元素比较 if (j < end && table[j] < table[j + 1]) { j ++; } //若父母结点值较小 if (temp < table[j]) { table[i] = table[j]; i = j; j = 2 * i + 1; } else { break; } } //当前子树的原根值调整后的位置 table[i] = temp; System.out.print("sift " + begin + ".." + end + " "); print(table); } /** * 归并排序 * @param x */ public static void mergeSort(int[] X) { System.out.println("归并排序"); //Y数组长度同X数组 int[] Y = new int[X.length]; //已排序的子序列长度,初值为1 int n = 1; while (n < X.length) { //一趟归并,将X书中中各子序列归并到Y中 mergepass(X, Y, n); print(Y); //子序列长度加倍 n *= 2; if (n < X.length) { //将Y书中各子序列再归并到X中 mergepass(X, Y, n); print(X); n *= 2; } } } /** * 一趟归并 * @param x * @param y * @param n */ private static void mergepass(int[] X, int[] Y, int n) { System.out.print("子序列长度n=" + n + " "); int i = 0; //X中若干相邻子序列归并到Y中 for (i = 0; i < X.length - 2 * n + 1; i += 2 * n) { //将X中两个相邻子序列一次归并到Y数组中 merge(X, Y, i, i + n, n); } if (i + n < X.length) { merge(X, Y, i, i + n, n); } else { //将X剩余元素复制到Y中 for (int j = i; j < X.length; j++) { Y[j] = X[j]; } } } /** * 一次归并 * @param X * @param Y * @param m * @param r * @param n */ private static void merge(int[] X, int[] Y, int m, int r, int n) { int i = m, j = r, k = m; //将X中两个相邻子序列归并到Y中 while (i < r && j < r + n && j < X.length) { //较小值复制到Y中 if (X[i] < X[j]) { Y[k++] = X[i++]; } else { Y[k++] = X[j++]; } } //将前一个子序列剩余元素复制到Y中 while (i < r) { Y[k++] = X[i++]; } //将后一个子序列剩余元素复制到Y中 while (j < r + n && j < X.length) { Y[k++] = X[j++]; } } /** * 对象数组的直接插入排序 * @param value */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static void insertSort(Comparable[] value) { System.out.println("直接插入排序"); //n - 1趟扫描 for (int i = 1;i < value.length; i++) { //每趟将value[i]插入到签名排序子序列中 Comparable temp = value[i]; int j; //将前面较大元素向后移动 for (j = i - 1; j >= 0 && temp.compareTo(value[j]) < 0; j--) { value[j + 1] = value[j]; } value[j + 1] = temp; System.out.print("第" + i + "趟"); //调用print(Object) 输出排序中间结果,可省略 print(value); } } /** * 判断一个数据序列是否为最大堆 * @param value * @return */ private static boolean isMaxHeap(int[] value) { //空序列不是堆 if (value.length == 0) { return false; } //i聪最深一棵子树的根结点开始 for (int i = value.length / 2 - 1; i >= 0; i--) { int j = 2 * i + 1; if (value[i] < value[j] || j + 1 < value.length && value[i] < value[j + 1]) { return false; } } return true; } /** * 判断一个数据序列是否为最小堆 * @param table * @return */ private static boolean isMinHeap(int[] value) { //空序列不是堆,若无此句,则空序列是堆,定义不同 if (value.length == 0) { return false; } //i从最深一棵子树的根结点开始 for (int i = value.length / 2 - 1; i >= 0; i--) { //j 是i的左孩子,肯定存在 int j = 2 * i + 1; if (value[i] > value[j] || j + 1 < value.length && value[i] > value[j + 1]) return false; } return true; } }
测试类:
package com.clarck.datastructure.array; /** * 随即数序列的直接插入排序 * * @author clarck * */ public class Array_test { //产生n个随机数,返回整型数组 public static int[] random(int n) { if (n <= 0) { return null; } int table[] = new int[n]; for (int i = 0; i < table.length; i++) { //产生一个0~99之间的随机数 table[i] = (int) (Math.random() * 100); } return table; } public static void main(String[] args) { // int[] table = {32,26,87,72,26,17}; //直接插入排序图9-1 int[] table = Array_test.random(9); // int[] table = {27,38,65,97,76,13,27,49,55,4}; //9.2.2希尔排序图9-2 // int[] table = {32,26,87,72,26,17}; //冒泡排序,图9-2 // int[] table = {1,2,3,4,5,6,7,8}; //冒泡排序,快速排序,最小堆 // int[] table = {1,3,2,4,5,8,6,7}; //冒泡排序 // int[] table = {4,5,8,1,2,7,3,6}; //冒泡排序 // int[] table = {8,7,6,5,4,3,2,1}; //冒泡排序,快速排序 // int[] table = {38,26,97,19,66,1,5,49}; //快速排序 ,图9-5 // int[] table = {38,97,26,19,38,5}; //直接选择排序,图9-7 // int[] table = {81,49,38,27,97,76,19,13}; //堆排序,图9-9 // int[] table = {36,74,68,61,55,15,4,12}; //堆排序 // int[] table = {52,26,97,19,66,8,49}; //归并排序,图9-11 // int[] table = {49,65,13,81,76,97,38,49}; // int[] table = {85,12,36,24,47,30,53,91,76}; System.out.print("关键字序列: "); Array.print(table); // Array.insertSort(table); // Array.shellSort(table); // Array.bubbleSort(table); // Array.quickSort(table); // Array.selectSort(table); // Array.heapSort_min(table); // Array.heapSort_max(table); Array.mergeSort(table); // int[] table = {13,27,38,49,97,76,49,81}; //最小堆 // int[] table = {9,13,62,69,76,92,96,72,96}; //最小堆 // int[] table = {9,13,62,59,26,92,56,72,96}; //不是最小堆 // System.out.println("最小堆序列? "+Array.isMinHeap(table)); // int[] table = {94,85,74,58,7,20,60,26,35}; //最大堆 // int[] table = {94,85,34,58,7,20,60,26,35}; //不是最大堆 // int[] table = {97,81,38,76,49,27,19,13,65}; //最大堆 // System.out.println("最大堆序列? "+Array.isMaxHeap(table)); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本