数据结构-排序
来源:互联网 发布:大数据修炼系统txt 编辑:程序博客网 时间:2024/06/08 06:59
排序
1.概念
- 稳定性: 排序前的前后位置和排序后的前后位置一致
- 内排序:排序过程中,所有待排序的记录全部被放置在内存中
外排序:排序过程中,由于排序的记录数过多,不能同时放在内存中,整个排序过程需要在内外存之间多次数据交换才能进行
插入排序类
- 直接插入排序 稳定
- 希尔排序 不稳定
- 选择排序类
- 简单选择排序 稳定
- 堆排序 不稳定
- 交换排序类
- 冒泡排序 稳定
- 快速排序 不稳定
- 归并排序类
- 归并排序 稳定
2.排序
2.1 冒泡排序
时间复杂度 n2
package com.sort;import java.util.Arrays;public class Bubble1 { public static void main(String[] args) { int[] arrs1 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; int[] arrs2 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; int[] arrs3 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; bubble1(arrs1); System.out.println(); bubble2(arrs2); System.out.println(); bubble3(arrs3); } // 优化后的冒泡 public static void bubble3(int[] arrs) { System.out.println("bubble3排序前:" + printArrays(arrs)); boolean flag = true; for (int i = 0; i < arrs.length - 1 && flag == true; i++) { flag = false; for (int j = arrs.length - 2; j >= i; j--) { if (arrs[j] > arrs[j + 1]) { swap(arrs, j, j + 1); flag = true; } } System.out.println("第" + (i + 1) + "次排序结果:" + printArrays(arrs)); } } // 正宗冒泡 public static void bubble2(int[] arrs) { System.out.println("bubble2排序前:" + printArrays(arrs)); for (int i = 0; i < arrs.length - 1; i++) { for (int j = arrs.length - 2; j >= i; j--) { if (arrs[j] > arrs[j + 1]) { swap(arrs, j, j + 1); } } System.out.println("第" + (i + 1) + "次排序结果:" + printArrays(arrs)); } } // 最简单 public static void bubble1(int[] arrs) { System.out.println("bubble1排序前:" + printArrays(arrs)); for (int i = 0; i < arrs.length - 1; i++) { for (int j = i + 1; j < arrs.length; j++) { if (arrs[i] > arrs[j]) { swap(arrs, i, j); } } System.out.println("第" + (i + 1) + "次排序结果:" + printArrays(arrs)); } } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
2.2 选择排序
与冒泡相比,少了许多交换swap操作。
时间复杂度 n2
package com.sort;import java.util.Arrays;public class Select1 { public static void main(String[] args) { int[] arrs1 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; select1(arrs1); } public static void select1(int[] arrs) { int minIndex = -1; for (int i = 0; i < arrs.length - 1; i++) { minIndex = i; for (int j = i + 1; j < arrs.length; j++) { if (arrs[j] < arrs[minIndex]) { minIndex = j; } } if (minIndex != i) { swap(arrs, i, minIndex); } print(i + 1, printArrays(arrs)); } } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "行" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
2.3 直接插入排序
时间复杂度 n2
有序的表中,将无序的表中的记录一个一个放入相应位置
package com.sort;import java.util.Arrays;public class DirectInsert { public static void main(String[] args) { int[] arrs1 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; directInsert(arrs1); } public static void directInsert(int[] arrs) { int temp = -1; for (int i = 1; i < arrs.length; i++) { // 第i个小于第i-1个。就是前一个小于后一个,则需要进行直接插入 if (arrs[i] < arrs[i - 1]) { temp = arrs[i]; for (int j = i - 1; j >= 0; j--) { if (arrs[j] > temp) { arrs[j + 1] = arrs[j]; // 如果j为0时,则因为后面不会在进行循环,所以此处需要判断j==0的情况 if (j == 0) { arrs[j] = temp; } } else { arrs[j + 1] = temp; break; } } } print(i, printArrays(arrs)); } } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "行" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
2.4 希尔排序
有一个步长step,每次根据这个步长进行调换元素。
不稳定的排序
package com.sort;import java.util.Arrays;public class Shell { public static void main(String[] args) { int[] arrs1 = { 9, 1, 5, 8, 3, 7, 4, 6, 2 }; System.out.println(printArrays(arrs1)); shell(arrs1); } public static void shell(int arrs[]) { int step = arrs.length; int temp = 0; int rowNumber = 1; int j = 0; do { step = step / 3 + 1; for (int i = step; i < arrs.length; i++) { if (arrs[i] < arrs[i - step]) { temp = arrs[i]; for (j = i - step; j >= 0 && temp < arrs[j]; j -= step) { swap(arrs, j + step, j); print(rowNumber, printArrays(arrs)); } arrs[j + step] = temp; } print(rowNumber, printArrays(arrs)); rowNumber++; } System.out.println(); } while (step > 1); } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "次" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
2.5 堆排序
- 小顶堆:在完全二叉树的前提下,每个结点的值都小于或者等于其左右孩子结点的值
- 大顶堆:在完全二叉树的前提下,每个结点的值都大于或者等于其左右孩子结点的值
不稳定的排序
先要构建大顶堆或小顶堆,然后进行排序,排序过程中又需要重构大顶堆或小顶堆。
时间复杂度 O(nlogn)
package com.sort;import java.util.Arrays;public class HeapSort { public static void main(String[] args) { int[] arrs1 = { 50, 10, 90, 30, 70, 40, 80, 60, 20 }; // , 11, 22, 33, 124, 54 // 构造大顶堆 heapOrder(arrs1); System.out.println(); // 堆排序 heapSort(arrs1); } public static void heapSort(int[] arrs) { System.out.println("原始样子:" + printArrays(arrs)); for (int i = arrs.length - 1; i > 0; i--) { swap(arrs, 0, i); heapAdjust(arrs, 0, i); print(i, printArrays(arrs)); } } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "次" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; } // 将无序堆调整为大顶堆 public static void heapOrder(int[] arrs) { System.out.println("构造大顶堆"); System.out.println(printArrays(arrs)); for (int i = arrs.length / 2 - 1; i >= 0; i--) { System.out.println("以顶点" + i + "(" + arrs[i] + ")进行构造" + printArrays(arrs)); heapAdjust(arrs, i, arrs.length); } } // 给定顶点,以该顶点为根节点,将该完全二叉树构造成大顶堆 public static void heapAdjust(int[] arrs, int start, int arrsNeedAdjustLength) { int temp, leftChildIndex, rightChildIndex; temp = arrs[start]; // 因为用数组存储,第一个结点的下标是0。每个结点的 // 左孩子下标 = 2 * 结点位置 + 1 // 右孩子下 标= 2 * 节点位置 + 2 for (int j = 2 * start + 1; j < arrsNeedAdjustLength; j = 2 * j + 1) { leftChildIndex = j; rightChildIndex = j + 1; // 如果存在右孩子,即右孩子的下标小于总的数组长度 // 并且右孩子的结点值大于左孩子的结点值 if (rightChildIndex < arrsNeedAdjustLength && arrs[leftChildIndex] < arrs[rightChildIndex]) { // 那么将j赋值为右孩子的下标。默认是左孩子的下标。 j = rightChildIndex; } // 如果结点的值大于 左孩子和右孩子中的大者,则退出循环, if (temp >= arrs[j]) { // 即父节点大于子结点,无需交换 break; } else { // 否则,父节点的值等于子结点中大者的值 arrs[start] = arrs[j]; // start坐标设置为子结点坐标,用于下次遍历使用 start = j; } } // 设置start坐标的值 arrs[start] = temp; }}
2.6 归并排序
递归实现, 时间复杂度O(nlogn),空间复杂度O(n+logn)
非递归实现(迭代)
比较占用内存,但却效率高且稳定的算法。
递归实现
package com.sort;import java.util.Arrays;public class MergingSort { public static void main(String[] args) { int arrs1[] = { 50, 10, 90, 30, 70, 40, 80, 60, 20 }; int arrs2[] = { 50, 10, 90, 30, 70, 40, 80, 60, 20 }; System.out.println(printArrays(arrs1)); System.out.println(printArrays(arrs2)); msort(arrs1, arrs2, 0, arrs1.length - 1); System.out.println(printArrays(arrs1)); System.out.println(printArrays(arrs2)); } // 递归 public static void msort(int[] arrs1, int[] arrs2, int startIndex, int endIndex) { int midIndex; int[] arrsTemp = new int[arrs1.length]; System.out.println(startIndex + " " + endIndex); if (startIndex == endIndex) { arrs2[startIndex] = arrs1[startIndex]; } else { midIndex = (startIndex + endIndex) / 2; msort(arrs1, arrsTemp, startIndex, midIndex); msort(arrs1, arrsTemp, midIndex + 1, endIndex); merge(arrsTemp, arrs2, startIndex, midIndex, endIndex); } } public static void merge(int arrs1[], int arrs2[], int startIndex, int midIndex, int endIndex) { int j, k, l; // 这个循环将midIndex前的数据和midIndex后的数据按大小合并。 // 类似于将两个有序的数组合并成一个数组。 for (j = midIndex + 1, k = startIndex; startIndex <= midIndex && j <= endIndex; k++) { if (arrs1[startIndex] < arrs1[j]) { arrs2[k] = arrs1[startIndex++]; } else { arrs2[k] = arrs1[j++]; } } // 数组后面多余的数 if (startIndex <= midIndex) { for (l = 0; l <= midIndex - startIndex; l++) { arrs2[k + l] = arrs1[startIndex + l]; } } // 数组后面多余的数 if (j <= endIndex) { for (l = 0; l <= endIndex - j; l++) { arrs2[k + l] = arrs1[j + l]; } } } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "次" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
迭代实现
package com.sort;import java.util.Arrays;public class MergingSort2 { public static void main(String[] args) { // 第一个数 0 用于占位,,, int arrs1[] = { 0, 50, 10, 90, 30, 70, 40, 80, 60, 20 }; // , 11, 22, 33, 124, 54 int arrs2[] = { 0, 50, 10, 90, 30, 70, 40, 80, 60, 20 }; System.out.println(printArrays(arrs1)); System.out.println(printArrays(arrs2)); int k = 1; while (k < arrs1.length) { mergePass(arrs1, arrs2, k, arrs1.length - 1); k = 2 * k; mergePass(arrs2, arrs1, k, arrs1.length - 1); k = 2 * k; } System.out.println(printArrays(arrs1)); System.out.println(printArrays(arrs2)); } // 迭代 public static void mergePass(int[] arrs1, int[] arrs2, int startIndex, int endIndex) { int i = 1, j; while (i <= endIndex - 2 * startIndex + 1) { merge(arrs1, arrs2, i, i + startIndex - 1, i + 2 * startIndex - 1); i = i + 2 * startIndex; } if (i < endIndex - startIndex + 1) { merge(arrs1, arrs2, i, i + startIndex - 1, endIndex); } else { for (j = i; j <= endIndex; j++) { arrs2[j] = arrs1[j]; } } } public static void merge(int[] arrs1, int[] arrs2, int startIndex, int midIndex, int endIndex) { int j, k, l; // 这个循环将midIndex前的数据和midIndex后的数据按大小合并。 // 类似于将两个有序的数组合并成一个数组。 for (j = midIndex + 1, k = startIndex; startIndex <= midIndex && j <= endIndex; k++) { if (arrs1[startIndex] < arrs1[j]) { arrs2[k] = arrs1[startIndex++]; } else { arrs2[k] = arrs1[j++]; } } // 数组后面多余的数 if (startIndex <= midIndex) { for (l = 0; l <= midIndex - startIndex; l++) { arrs2[k + l] = arrs1[startIndex + l]; } } // 数组后面多余的数 if (j <= endIndex) { for (l = 0; l <= endIndex - j; l++) { arrs2[k + l] = arrs1[j + l]; } } } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "次" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
2.7 快速排序
时间复杂度 nlogn
空间复杂度 logn
package com.sort;import java.util.Arrays;public class QuickSort { public static void main(String[] args) { // 第一个数 0 用于占位,,, int arrs1[] = { 0, 50, 10, 90, 30, 70, 40, 80, 60, 20 }; System.out.println(printArrays(arrs1)); qSort(arrs1, 0, arrs1.length - 1); System.out.println(printArrays(arrs1)); } public static void qSort(int[] arrs, int low, int high) { int pivot; if (low < high) { pivot = partition(arrs, low, high); qSort(arrs, low, pivot - 1); qSort(arrs, pivot + 1, high); } } public static int partition(int[] arrs, int low, int high) { int pivotkey = arrs[low]; while (low < high) { while (low < high && arrs[high] >= pivotkey) { high--; } swap(arrs, low, high); while (low < high && arrs[low] <= pivotkey) { high--; } swap(arrs, low, high); } return low; } public static void print(int rowNumber, String dataString) { System.out.println("第" + rowNumber + "次" + dataString); } public static String printArrays(int[] arrs) { return Arrays.toString(arrs); } public static void swap(int[] arrs, int i, int j) { int temp = arrs[i]; arrs[i] = arrs[j]; arrs[j] = temp; }}
阅读全文
0 0
- 数据结构-排序
- 数据结构----排序
- 数据结构 - 排序
- 数据结构--排序
- 数据结构排序
- 数据结构 排序
- 数据结构排序
- 数据结构-----排序
- 数据结构排序
- 数据结构--排序
- 数据结构 排序
- 排序 - 数据结构
- 数据结构-排序
- 数据结构 - 排序
- 【数据结构】排序
- 数据结构 - 排序
- 数据结构-排序
- 数据结构排序
- Spanned及CharSequence
- c# Console.WriteLine() Console.ReadLine()
- aop源码解析二:postProcessBeforeInstantiation
- hibernate的get,load,persist方法比较(二)
- MySQL远程连接提示Accesss denied for user 'root'@'此处为你自己的ip'(using password:YES)
- 数据结构-排序
- makefile入门
- word2016与mathtype6.9的兼容
- dd iso
- 单例
- 递归经典算法 汉诺塔问题
- ceil函数
- 实体类和JSON对象之间相互转化
- linux C总结篇(线程)上