算法篇2:排序算法(中篇)
六:归并排序
基本思路:
将每条记录看成一个有序的子表,然后将有序表进行合并排序,直至完全有序
举例说明:
初始需排序数组:int[] arr = {6,3,8,2,9,1}
代码实现:
1 package com.xqc.sort; 2 3 import java.util.Arrays; 4 5 public class MergeSort { 6 public static void main(String []args){ 7 //步骤1:初始化数组 8 int[] arr={6,3,8,2,9,1}; 9 System.out.println("排序前数组为:"+Arrays.toString(arr)); 10 //步骤二:归并排序 11 int []temp = new int[arr.length];//在排序前,先建好一个长度等于原数组长度的临时数组,避免递归中频繁开辟空间 12 mergesort(arr,0,arr.length-1,temp); 13 //步骤三:输出排序后数组 14 System.out.println("排序后数组为:"+Arrays.toString(arr)); 15 } 16 private static void mergesort(int[] arr,int left,int right,int []temp){ 17 if(left<right){ 18 int mid = (left+right)/2; 19 mergesort(arr,left,mid,temp);//左边归并排序,使得左子序列有序 20 mergesort(arr,mid+1,right,temp);//右边归并排序,使得右子序列有序 21 merge(arr,left,mid,right,temp);//将两个有序子数组合并操作 22 } 23 } 24 private static void merge(int[] arr,int left,int mid,int right,int[] temp){ 25 int i = left;//左序列指针 26 int j = mid+1;//右序列指针 27 int t = 0;//临时数组指针 28 while (i<=mid && j<=right){ 29 if(arr[i]<=arr[j]){ 30 temp[t++] = arr[i++]; 31 }else { 32 temp[t++] = arr[j++]; 33 } 34 } 35 while(i<=mid){//将左边剩余元素填充进temp中 36 temp[t++] = arr[i++]; 37 } 38 while(j<=right){//将右序列剩余元素填充进temp中 39 temp[t++] = arr[j++]; 40 } 41 t = 0; 42 //将temp中的元素全部拷贝到原数组中 43 while(left <= right){ 44 arr[left++] = temp[t++]; 45 } 46 } 47 }
注:将有序表合并的简单图解(前两天刚看到别人画的,很好,盗图 https://www.cnblogs.com/chengxiao/p/6194356.html),即上述代码中的 merge()方法
七:堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,堆分为两种,大根堆和小根堆,大根堆的要求是每个节点的值都不大于其父节点的值,小根堆则相反
基本思路:
先构造出来大根堆(假设从小到大排序),然后取出堆顶元素(也就是最大的元素),放到数组的最后面,然后再将剩余的元素构造大根堆,再取出堆顶元素放到数组倒数第二个位置,依次类 推,知道所有的元素都放到数组中,排序就完成了
注:升序排序建立大根堆,降序排列建立小根堆
举例说明:
(原图出处:https://blog.csdn.net/qq_21492635/article/details/73105580)
初始化堆:
堆排序处理:
代码实现:
1 package com.xqc.sort; 2 3 import java.util.Arrays; 4 5 public class HeapSort 6 { 7 public static void main(String[] args) 8 { 9 //步骤1:初始化数组 10 int[] arr={6,3,8,2,9,1}; 11 System.out.println("排序前数组为:"+Arrays.toString(arr)); 12 //步骤二:堆排序 13 HeapSortFaction(arr); 14 //步骤三:显示排序后数组 15 System.out.println("排序后数组为:"+Arrays.toString(arr)); 16 } 17 //堆排序函数 18 public static void HeapSortFaction(int[] arr) 19 { 20 int n = arr.length-1; 21 for(int i=(n-1)/2;i>=0;i--) 22 { 23 //构造大顶堆,从下往上构造 24 //i为最后一个根节点,n为数组最后一个元素的下标 25 HeapAdjust(arr,i,n); 26 } 27 for(int i=n;i>0;i--) 28 { 29 //把最大的数,也就是顶放到最后 30 //i每次减一,因为要放的位置每次都不是固定的 31 swap(arr,i); 32 //再构造大顶堆 33 HeapAdjust(arr,0,i-1); 34 } 35 } 36 37 //构造大顶堆函数,parent为父节点,length为数组最后一个元素的下标 38 public static void HeapAdjust(int[] arr,int parent,int length) 39 { 40 //定义临时变量存储父节点中的数据,防止被覆盖 41 int temp = arr[parent]; 42 //2*parent+1是其左孩子节点 43 for(int i=parent*2+1;i<=length;i=i*2+1) 44 { 45 //如果左孩子大于右孩子,就让i指向右孩子 46 if(i<length && arr[i]<arr[i+1]) 47 { 48 i++; 49 } 50 //如果父节点大于或者等于较大的孩子,那就退出循环 51 if(temp>=arr[i]) 52 { 53 break; 54 } 55 //如果父节点小于孩子节点,那就把孩子节点放到父节点上 56 arr[parent] = arr[i]; 57 //把孩子节点的下标赋值给parent 58 //让其继续循环以保证大根堆构造正确 59 parent = i; 60 } 61 //将刚刚的父节点中的数据赋值给新位置 62 arr[parent] = temp; 63 } 64 65 //定义swap函数 66 //功能:将跟元素与最后位置的元素交换 67 //注意这里的最后是相对最后,是在变化的 68 public static void swap(int[] arr,int i) 69 { 70 int temp = arr[0]; 71 arr[0] = arr[i]; 72 arr[i] = temp; 73 } 74 }
文章可随意参考借鉴,欢迎大家指正错误,如果感觉有用,点个赞就好