排序算法总结
1.桶排序
public static void BucketSort(int[] nums){ //这里需要知道数组的最大值,作为桶的个数 int[] buckets = new int[11]; //装桶 for (int i = 0; i < nums.length; i++) { buckets[nums[i]]++; } int j = 0; //出桶 for (int i = 0; i < buckets.length; i++) { while (buckets[i]>0) { nums[j] = i; j++; buckets[i]--; } } System.out.println(Arrays.toString(nums)); }
2.冒泡排序
public static void Bubble(int[] nums){ /* 冒泡和选择的区别是: 冒泡是从上到下依次确定好每个位置的数字,每次把较小的数字交换到上边 选择是每次找到最小数字,然后放到应该的位置 */ //冒泡次数是数组长度,每次冒泡都确定顶部一个位置的数字 for (int i = 0; i < nums.length-1; i++) { //每次都是从数组底部开始取,依次向上 for (int j = nums.length-1; j > i ; j--) { if (nums[j]<nums[j-1]) { int temp = nums[j]; nums[j] = nums[j-1]; nums[j-1] = temp; } } } System.out.println(Arrays.toString(nums)); }
3.选择排序
public static void SelectionSort(int[] nums){ //每次从当前最开始位置(每次都往下一个)开始,找到最小的数,排到上边 for (int i = 0; i < nums.length-1; i++) { //记录最小数的index int min = i; for (int j = i+1; j < nums.length; j++) { //更新最小数index if (nums[j]<nums[min]) min = j; } //找到最小数后交换 if (i!=min) { int temp = nums[min]; nums[min] = nums[i]; nums[i] = temp; } } System.out.println(Arrays.toString(nums)); }
4.三数取中快排
public static void QuickSort(int[] nums,int lo,int hi){ if (lo>=hi) return; //三数取中进行选择基准值 int mid = (lo+hi)/2; if (nums[mid]>nums[hi]) swap(mid,hi,nums); if (nums[lo]>nums[hi]) swap(lo,hi,nums); if (nums[mid]>nums[lo]) swap(lo,mid,nums); //现在lo位置是中间数 int left = lo; int right = hi; while (lo<hi) { //必须从基准对面开始走,因为对面哨兵停止的位置应该和基准位置交换 while (nums[hi]>=nums[left] && lo<hi) hi--; while (nums[lo]<=nums[left] && lo<hi) lo++; //交换不符合者 swap(lo,hi,nums); } swap(hi,left,nums); QuickSort(nums,left,hi-1); QuickSort(nums,hi+1,right); } public static void swap(int i,int j,int[] nums){ int temp = nums[j]; nums[j] = nums[i]; nums[i] = temp; }
5.归并排序
/* 思路就是将两个有序数组进行组合,通过递归得到左右排序好的数组 */ //组合函数 public void combine(int[] a,int sta,int mid,int end,int[] res) { int f = sta; int sta2 = mid+1; int i = 0; //两个数组都没有遍历完 while (sta<=mid&&sta2<=end) { if (a[sta]<a[sta2]) res[i++] = a[sta++]; else res[i++] = a[sta2++]; } while (sta<=mid) res[i++] = a[sta++]; while (sta2<=end) res[i++] = a[sta2++]; //将排序结果添加到a中,让a形成有序数组 for (int j = 0; j < i; j++) { a[j+f] = res[j]; } } public void sort(int[] a ,int sta,int end,int[] res) { //分治思想把子数组排为有序数组 if (sta<end) { int mid = (sta+end)/2; sort(a,sta,mid,res); sort(a,mid+1,end,res); combine(a,sta,mid,end,res); } } public void mergeSort(int[] a) { int[] res = new int[a.length]; sort(a,0,a.length-1,res); }
6.堆排序
public void sort(int[] nums) { //要设置一个变量记录当前堆的大小,每次取数,堆会少最后一个节点 int l = nums.length; //构建大根堆,降序则构建小根堆。大根堆是一个完全二叉树,且父节点一定不小于子节点 //数组一开始可以看成一个堆,不过需要调整。从最后一个非叶节点开始调整,调整到根节点 //最后一个非叶节点的index是n/2-1; for (int i = (l/2)-1; i >=0 ; i--) { adjust(nums,i,l); } //开始取数 while (l>1){ //取数就是把最大的数(堆顶)放到最后,然后最后那个节点就脱离堆(尺寸-1) swap(nums,0,l-1); l--; //每次交换结束都要进行调整 adjust(nums,0,l); } } public void adjust(int[] nums,int index,int size){ /* 输入的是待调整堆和调整范围(从index节点处开始调整,默认前边是调整好的) */ //获取完全二叉树中子节点的index int l = index*2+1; int r = index*2+2; int max = index; //找到这一家庭中最大值是谁,有可能有的孩子不存在,所以要判断 if (l<size && nums[max]<nums[l]) max = l; if (r<size && nums[max]<nums[r]) max = r; //如果需要调整,就调整 if (max!=index) { swap(nums,max,index); //调整后有可能被调整的子节点会不符合规定,所以要调整孩子节点 adjust(nums,max,size); } } public void swap(int[] nums,int i,int j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; }
7.插入排序
public void sort(int[] nums){ /* 从前两个开始,排好序,以后从第三个开始后,前边的就是都排好的了,大的数往后挪,知道找到当前数的位置 */ if (nums.length<2) return; //外层代表当前数 for (int i = 1; i < nums.length; i++) { int temp = nums[i]; int j = i-1; while (j>=0&&temp<nums[j]) { nums[j+1] = nums[j]; j--; } nums[j+1] = temp; } }
8.希尔排序,希尔排序是在插入排序的基础上做的优化
请看大牛整理的:https://www.cnblogs.com/chengxiao/p/6104371.html