基础排序算法 java 实现(冒泡、选择、插入、快排、归并、堆排)
2018-01-23 17:00
681 查看
package demo; import java.util.Arrays; public class SortUtil { private static void printArr(int[] arr) { System.out.println(Arrays.toString(arr)); } private static void checkSort(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { if (arr[i] > arr[i + 1]) { throw new RuntimeException("Sort Error!"); } } } private static void swap(int[] arr, int i, int j) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } // 本机测试 public static void main(String[] args) { // int[] arr = {4, 3, 5}; int[] arr = new int[50000 * 100]; java.util.Random random = new java.util.Random(); for (int i = 0; i < arr.length; i++) { arr[i] = random.nextInt(arr.length); } // System.out.println("排序前:"); // printArr(arr); long s = System.currentTimeMillis(); // bubbleSort(arr);// 50000 数据 5000+ ms // selectSort(arr);// 50000 数据 1700+ ms // insertSort(arr);// 50000 数据 360+ ms quickSort(arr, 0, arr.length - 1);// 50000 * 100 数据 770 ms // mergeSort(arr);// 50000 * 100 数据 1300 ms // mergeSort(arr, 0, arr.length - 1);// 50000 * 100 数据 1300 ms // heapSort(arr);// 50000 * 100 数据 1650 ms long e = System.currentTimeMillis(); System.out.println("耗时:" + (e - s)); checkSort(arr); System.out.println("排序正确!"); // System.out.println("排序后:"); // printArr(arr); } private static void bubbleSort(int[] arr) { int len = arr.length; for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放 for (int j = len - 1; j > i; j--) { // 从后往前,把最小(大)的挪动到目标位置 if (arr[j] < arr[j - 1]) { // 后面的大于前面 swap(arr, j, j - 1);//如果没有发送交互则表示排序已经完成,但会多n次判断 } } } } private static void selectSort(int[] arr) { int len = arr.length; for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放 int min = i; for (int j = i + 1; j < len; j++) { if (arr[j] < arr[min]) { // 后面的大于前面 min = j; } } swap(arr, i, min); } } private static void insertSort(int[] arr) { for (int i = 1; i < arr.length; i++) {// 第一个不需要插入排序 int temp = arr[i]; int j = i - 1; while (j >= 0 && temp < arr[j]) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = temp; } } /*** quick ***/ private static void quickSort(int[] arr, int left, int right) { if (left >= right) return; int pivotIndex = partition(arr, left, right); quickSort(arr, left, pivotIndex - 1);//排序 target 前面的 quickSort(arr, pivotIndex + 1, right);//排序 target 后面的 } private static int partition(int[] arr, int left, int right) { int pivot = arr[right];//堆排序是原地排序,这个额外空间可以省去的,这里为了语义明确在此声明 int target = left; for (int i = left; i < right; i++) { if (arr[i] < pivot) { swap(arr, target++, i); } } swap(arr, target, right);// target 已经处在正确的位置 return target; } /*** merge:递归实现 从外向里 ***/ private static void mergeSort(int[] arr, int left, int right) { if (left == right) return;//待排序列长度为1 int middle = (left + right) / 2; mergeSort(arr, left, middle); mergeSort(arr, middle + 1, right); merge(arr, left, middle, right); } /*** merge:迭代实现 从里向外 ***/ private static void mergeSort(int[] arr) { int len = arr.length; int left;//需要归并的左坐标 int middle;//需要归并的中坐标(定义为左侧的结束端坐标),也就是步长的最后一个 int right;//需要归并的右坐标 for (int mergeLen = 1; mergeLen < len; mergeLen *= 2) { left = 0; while (left + mergeLen < len) { // 有后面的数组需要归并 middle = left + mergeLen - 1; right = middle + mergeLen < len ? middle + mergeLen : len - 1; merge(arr, left, middle, right); left = right + 1; } } } private static void merge(int[] arr, int left, int leftEnd, int right) { int len = right - left + 1; int[] temp = new int[len];//辅助空间 int tempIndex = 0;//辅助空间指针 int i = left;//左侧指针 int j = leftEnd + 1;//右侧指针 while (i <= leftEnd && j <= right) { if (arr[i] <= arr[j]) {// 带等号保证归并排序的稳定性 temp[tempIndex++] = arr[i++]; } else { temp[tempIndex++] = arr[j++]; } } while (i <= leftEnd) { temp[tempIndex++] = arr[i++];//左侧数组未 } while (j <= right) { temp[tempIndex++] = arr[j++]; } for (int k = 0; k < len; k++) { arr[left + k] = temp[k];//将辅助空间内容替换至真实数组的 left-right 空间 } } /*** heap ***/ private static void heapSort(int[] arr) { buildHeap(arr);//初始化大顶堆 int maxHeapIndex = arr.length - 1; while (maxHeapIndex > 0) {// 堆(无序区)元素个数大于1,未完成排序 swap(arr, 0, maxHeapIndex--);// 此处交换操作很有可能把后面元素的稳定性打乱,所以堆排序是不稳定的排序算法 adjustHeap(arr, 0, maxHeapIndex);// 从新的堆顶元素开始向下进行堆调整,时间复杂度O(logn) } } private static void buildHeap(int[] arr) { // 建堆,时间复杂度O(n) int len = arr.length; for (int i = len / 2 - 1; i >= 0; i--) {//从最后一个非叶子节点开始,向上调堆,当i==0时,所有堆成为最大堆 adjustHeap(arr, i, len - 1); } } private static void adjustHeap(int[] arr, int i, int maxIndex) { int leftChild = i * 2 + 1; int rightChild = i * 2 + 2; int max = i; if (leftChild <= maxIndex && (arr[leftChild] > arr[max])) { max = leftChild; } if (rightChild <= maxIndex && (arr[rightChild] > arr[max])) { max = rightChild; } if (max != i) { swap(arr, i, max);//把最大的换到当前堆顶,然后继续调剂被破坏的子堆 adjustHeap(arr, max, maxIndex);// 保证被破坏的子堆继续维持大顶堆性质 } } }
相关文章推荐
- Java 基础排序算法(冒泡,比较,插入,选择,希尔,堆,归并)
- 基础排序算法,java实现(快速,冒泡,选择,堆排序,插入)
- 《冒泡,选择,插入,归并,希尔,快速》排序算法java实现一览
- 排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序
- 常见排序算法(冒泡、选择、插入、快速、归并C++实现)
- 排序算法复习(Java实现):插入,冒泡,选择,Shell,快速排序, 归并排序,堆排序,桶式排序,基数排序
- 排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序
- 排序算法复习(Java实现)(一): 插入,冒泡,选择,快速排序
- 排序算法复习(Java实现): 插入,冒泡,选择,Shell,快速排序
- 常用排序算法的c++实现(冒泡,选择,插入,堆,shell,快速,归并 )与sort()对比
- 排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序
- 6种排序算法的简洁实现:冒泡、选择、插入、归并、快速、堆
- 常见内部排序算法 简单数组实现与分析(快速(偶原创partition函数,望众高手指正)、归并、希尔、插入、选择、冒泡)
- 自己动手实现数据结构——排序算法1(冒泡、插入、归并、简单选择)(C++实现)
- 【转】排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序
- Java实现的排序算法及比较 [冒泡,选择,插入,归并,希尔,快排]
- 6种排序算法的简洁实现:冒泡、选择、插入、归并、快速、堆
- 6种排序算法的简洁实现:冒泡、选择、插入、归并、快速、堆
- java排序算法代码实现(冒泡、选择、插入)
- 排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序