一、内部排序
1、冒泡排序(交换排序)
public void maopaosort(int[] nums) { int len = nums.length; if(len<=1) { return; } boolean flag = true; for(int i=0;i<len-1;i++) { flag = true; for(int j=0;j<len-1-i;j++) { if(nums[j]>nums[j+1]) { flag = false; nums[j] = nums[j]^nums[j+1]; nums[j+1] = nums[j]^nums[j+1]; nums[j] = nums[j]^nums[j+1]; } } if(flag) { break; } } }
2、简单选择排序(选择排序)
public void choosesort(int[] nums) { int len = nums.length; if(len<=1) { return; } int k = 0; int item = 0; for(int i=0;i<len-1;i++) { item = nums[i]; k = i; for(int j=i+1;j<len;j++) { if(nums[j]<item) { item = nums[j]; k = j; } } if(k!=i) { nums[i] = nums[i]^nums[k]; nums[k] = nums[i]^nums[k]; nums[i] = nums[i]^nums[k]; } } }
3、快速排序(交换排序)
解题思路:递归,自顶向下,分冶法
经典的快速排序:
public static void sort(int[] nums,int start,int end) { if(nums==null||start>=end) { return; } int temp = nums[start]; int begin = start; int last = end; while(begin<last) { while(begin<last&&nums[last]>=temp) --last; nums[begin] = nums[last]; while(begin<last&&nums[begin]<=temp) ++begin; nums[last] = nums[begin]; } nums[begin] = temp; sort(nums,start,begin-1); sort(nums,begin+1,end); }
快排另一思路(个人觉得效率会高一些):
public void quicksort(int[] nums,int start,int end) { if(start>=end) { return; } int low = start; int high = end; int t = nums[start]; while(low<high) { while(low<high&&nums[high]>=t) high--; if(low==high) { break; } nums[low] = nums[high]; ++low; while(low<high&&nums[low]<=t) low++; if(low==high) { break; } nums[high] = nums[low]; --high; } //最后循环出来的结局是low==high nums[low] = t; quicksort(nums,start,low-1); quicksort(nums,low+1,end); }
快速排序总结:
1、终止条件
2、while循环
3、两边递归
public void sortImpl(int[] nums, int begin, int last) { if(begin>=last) { return; } int start = begin; int end = last; int temp = nums[start]; while(start<end) { while(start<end&&nums[end]>=temp) { --end; } nums[start] = nums[end]; while(start<end&&nums[start]<=temp) { ++start; } nums[end]=nums[start]; } nums[start] = temp; sortImpl(nums, begin,start-1); sortImpl(nums, start+1,last); }
4、堆排序(选择排序)
构造堆:采用筛选法;一般升序采用大顶堆,降序采用小顶堆。
解题思路:二叉树+递归
public void heapsort(int[] nums) { int len = nums.length; if(len<=1) { return; } for(int i=len/2-1;i>=0;i--) { createheap(nums,len,i); } for(int i=len-1;i>0;i--) { nums[i] = nums[i]^nums[0]; nums[0] = nums[i]^nums[0]; nums[i] = nums[i]^nums[0]; createheap(nums,i,0); } } public void createheap(int[] nums, int len, int parent) { if(2*parent+2<=len-1&&nums[parent]<nums[2*parent+2]) { nums[parent] = nums[parent]^nums[2*parent+2]; nums[2*parent+2] = nums[parent]^nums[2*parent+2]; nums[parent] = nums[parent]^nums[2*parent+2]; createheap(nums,len,2*parent+2); } if(2*parent+1<=len-1&&nums[parent]<nums[2*parent+1]) { nums[parent] = nums[parent]^nums[2*parent+1]; nums[2*parent+1] = nums[parent]^nums[2*parent+1]; nums[parent] = nums[parent]^nums[2*parent+1]; createheap(nums,len,2*parent+1); } }
堆排序总结:
1、建堆
2、排序
3、注意堆排序的精髓,减少交换次数很重要
public void sortImpl(int[] nums, int len) { // TODO Auto-generated method stub for(int i=len/2-1;i>=0;--i) { heapSort(nums, len, i); } int temp = 0; for(int i=len - 1;i>0;--i) { temp = nums[0]; nums[0] = nums[i]; nums[i] = temp; heapSort(nums, i, 0); } } public void heapSort(int[] nums, int len, int parent) { int child1 = 2*parent+1; int child2 = 2*parent+2; int temp = 0; if(child2<len) { if(nums[child1]>nums[child2]) { if(nums[child1]>nums[parent]) { temp = nums[parent]; nums[parent] = nums[child1]; nums[child1] = temp; heapSort(nums, len, child1); } }else { if(nums[child2]>nums[parent]) { temp = nums[parent]; nums[parent] = nums[child2]; nums[child2] = temp; heapSort(nums, len, child2); } } }else { if(child1<len&&nums[child1]>nums[parent]) { temp = nums[child1]; nums[child1] = nums[parent]; nums[parent] = temp; heapSort(nums, len, child1); } } }
5、直接插入排序
public void directinsertsort(int[] nums){ int len = nums.length; if(len<=1) { return; } int t = 0; int j=0; for(int i=1;i<len;i++) { t = nums[i]; for(j=0;j<i;j++) { if(t<nums[j]) { break; } } //这里是折半插入排序的代码大家也可以看一下 // int high = i-1; // int low = 0; // int temp = 0; // while(low<=high) { // temp = (low+high)/2; // if(nums[temp]<=nums[i]) { // low=temp+1; // }else { // high = temp-1; // } // } // j=low; for(int k=i;k>=j+1;k--) { nums[k]=nums[k-1]; } nums[j] = t; } }
直接插入排序总结:
1、正常的插入排序思想
2、不需要查找的过程才为最佳
3、处理结尾条件
public void sortImpl(int[] nums, int len) { // TODO Auto-generated method stub int temp = 0; int j = 0; for(int i = 1;i<len;++i) { if(nums[i]<nums[i-1]) { temp = nums[i]; for(j=i;j>0;--j) { if(temp<nums[j-1]) { nums[j] = nums[j-1]; }else { nums[j] = temp; break; } } if(j==0){ nums[j] = temp; } } } }
6、希尔排序(插入排序)
public void shellsort(int[] nums) { int len = nums.length; if(len<2) { return; } for(int step=len/2;step>=1;step/=2) { unitdirectsort(nums, len, step); } } public static void unitdirectsort(int[] nums,int len, int step) { int t = 0; int j = 0; for(int k=0;k<step;k++) { for(int i=k+step;i<len;i+=step) { t = nums[i]; for(j=k;j<i;j+=step) { if(nums[i]<nums[j]) { break; } } for(int m=i;m>=j+step;m-=step) { nums[m] = nums[m-step]; } nums[j] = t; } } }
希尔排序总结:
public void sortImpl(int[] nums, int len) { // TODO Auto-generated method stub if(len==1) { return; } int step=1; while(step<=len/3) { step = step*3+1; } for(int i = step;i>=1;i=(i-1)/3) { shellSort(nums, len, i); } } public void shellSort(int[] nums, int len, int step) { int temp = 0; int k = 0; for(int i=step;i<len;++i) { if(nums[i]<nums[i-step]) { temp = nums[i]; for(k=i;k>=step;k-=step) { if(temp<nums[k-step]) { nums[k] = nums[k-step]; }else { nums[k] = temp; break; } } if(k<step) { nums[k] = temp; } } } }
希尔排序(并行算法):
public class CurrentShellSort extends AbstractSort { private static Executor pool = Executors.newFixedThreadPool(8); public CurrentShellSort() { // TODO Auto-generated constructor stub } @Override public void sortImpl(int[] nums, int start, int end) { // TODO Auto-generated method stub } @Override public void sortImpl(int[] nums, int len) { // TODO Auto-generated method stub if(len<=1) { return; } int h = 1; while(h<=len/3) { h = h*3 + 1; } for(int step = h;step>=1;step=(step-1)/3) { shellSort(nums, len, step); } } public void shellSort(int[] nums, int len, int step) { int temp = 0; int k = 0; CountDownLatch latch = null; if(len>step) { latch = new CountDownLatch(Math.min(2*step, len)-step); } for(int i=step;i<Math.min(2*step, len);++i) { pool.execute(new ShellSortTask(nums, i, step, len, latch)); } try { latch.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } class ShellSortTask implements Runnable{ private int[] nums = null; private int start = 0; private int step = 0; private int len = 0; private CountDownLatch latch = null; public ShellSortTask(int[] nums, int start, int step, int len,CountDownLatch latch) { // TODO Auto-generated constructor stub this.nums = nums; this.start = start; this.step = step; this.len = len; this.latch = latch; } @Override public void run() { // TODO Auto-generated method stub int temp = 0; int k = 0; for(int i = start;i<len;i+=step) { if(nums[i]<nums[i-step]) { temp = nums[i]; for(k = i;k>=step;k-=step) { if(temp<nums[k-step]) { nums[k] = nums[k-step]; }else { nums[k] = temp; break; } } if(k<step) { nums[k] = temp; } } } latch.countDown(); } }
7、归并排序(非递归)
解题思路:分冶法+自底向上
public void mergesort(int[] nums) { int len = nums.length; if(len<=1) { return; } int[] nums2 = new int[len]; boolean flag = true; for(int step = 1;step<len;step*=2) { if(flag) { unitmergesort(nums, nums2,len, step); flag = false; }else { unitmergesort(nums2, nums,len, step); flag = true; } } //注意这里最后的处理结果要放到nums里面 if(!flag) { for(int i=0;i<len;i++) { nums[i] = nums2[i]; } } } public static void unitmergesort(int[] nums,int[] nums2,int len,int step) { int m = 0; int n = 0; int k=0; int i=0; for(i=0;i<len-2*step+1;i+=2*step) { m=i; n=i+step; for(k=i;k<i+2*step&&m<i+step&&n<i+2*step;k++) { if(nums[m]<nums[n]) { nums2[k] = nums[m++]; }else { nums2[k] = nums[n++]; } } while(m<i+step) nums2[k++] = nums[m++]; while(n<i+2*step) nums2[k++] = nums[n++]; } //注意多余元素的处理,这里的处理非常重要 if(i<len-step) { m=i; n=i+step; for(k=i;k<len&&m<i+step&&n<len;k++) { if(nums[m]<nums[n]) { nums2[k] = nums[m++]; }else { nums2[k] = nums[n++]; } } while(m<i+step) nums2[k++] = nums[m++]; while(n<len) nums2[k++] = nums[n++]; } }
第二种比较简单的思路:
public void sortImpl(int[] nums, int start, int end) { // TODO Auto-generated method stub int len = end - start + 1; int[] nums2 = new int[len]; boolean flag = true; for(int step = 1; step < len; step *= 2) { if(flag) { unitSortImpl(nums,nums2,len,step); flag = false; }else { unitSortImpl(nums2,nums,len,step); flag = true; } } if(!flag) { System.arraycopy(nums2, 0, nums, 0, len); } } public void unitSortImpl(int[] nums, int[] nums2,int len, int step) { int m = 0 ; int n = 0; int s = 0; int t = 0; int j = 0; for(int i = 0;i+step<len;i+=2*step) { m = i; s = i+step; n = s; t = i+2*step>len?len:i+2*step; while(m<s&&n<t) { if(nums[m]<=nums[n]) { nums2[j++] = nums[m++]; }else { nums2[j++] = nums[n++]; } } while(m<s) { nums2[j++] = nums[m++]; } while(n<t) { nums2[j++] = nums[n++]; } } }
归并排序总结:
1、创建另外一个数组nums2
2、从step等于1开始~step<len归并
3、归并的方法,注意结尾的处理
4、如果结果在nums2中,需要拷贝到nums里面
public void sortImpl(int[] nums, int len) { // TODO Auto-generated method stub int[] nums2 = new int[len]; boolean flag = true; for(int step = 1; step < len; step *= 2) { if(flag) { unitSortImpl(nums,nums2,len,step); flag = false; }else { unitSortImpl(nums2,nums,len,step); flag = true; } } if(!flag) { System.arraycopy(nums2, 0, nums, 0, len); } } public void unitSortImpl(int[] nums, int[] nums2,int len, int step) { int m = 0 ; int n = 0; int s = 0; int t = 0; int j = 0; for(int i = 0;i+step<len;i+=2*step) { m = i; j = m; s = i+step; n = s; t = i+2*step>len?len:i+2*step; while(m<s&&n<t) { if(nums[m]<=nums[n]) { nums2[j++] = nums[m++]; }else { nums2[j++] = nums[n++]; } } while(m<s) { nums2[j++] = nums[m++]; } while(n<t) { nums2[j++] = nums[n++]; } } while(j<len) { nums2[j]=nums[j]; ++j; } }
8、归并排序(递归)
解题思路:分冶法+自顶向下
最后所有的分支都递归到了len==1而截止。
注意:这里的nums和nums2最开始里面必须有相同的元素,最开使nums2的元素不能是其他值,也就是排序前要把nums的值全部复制到nums2里面;还有就是最后的结果是放在nums2里面了。
public void mergesort(int[] nums,int[] nums2,int len,int start) { if(len==1) { nums2[0]=nums[0]; return; } int mid = 0; mid = len/2; mergesort(nums2, nums, mid, start); mergesort(nums2, nums, len-mid,start+mid); unitmergesort(nums, nums2, len,start,mid); } public static void unitmergesort(int[] nums,int[] nums2,int len,int start,int step) { int m =start; int n = start+step; int i = 0; for(i=start;i<start+len&&m<start+step&&n<start+len;i++) { if(nums[m]<nums[n]) { nums2[i]=nums[m++]; }else { nums2[i]=nums[n++]; } } while(m<start+step) nums2[i++] = nums[m++]; while(n<start+len) nums2[i++] = nums[n++]; }
第二种思路:
public void sortImpl(int[] nums, int start, int end) { // TODO Auto-generated method stub int len = end - start + 1; int[] nums2 = new int[len]; System.arraycopy(nums, 0, nums2, 0, len); mergeSort(nums,nums2,0,end); } public void mergeSort(int[] nums, int[] nums2, int start, int end) { if(end-start<=0) { return; } int mid = (start+end)/2; mergeSort(nums, nums2, start, mid); mergeSort(nums, nums2, mid+1, end); combineMergeSort(nums2, nums, start, mid, end); } public void combineMergeSort(int[] nums, int[] nums2, int start, int mid, int end) { int m = start; int n = mid + 1; int s = n; int t = end + 1; int j = start; while(m<s&&n<t) { if(nums[m]<=nums[n]) { nums2[j++] = nums[m++]; }else { nums2[j++] = nums[n++]; } } while(m<s) { nums2[j++] = nums[m++]; } while(n<t) { nums2[j++] = nums[n++]; } }
归并排序总结:
1、创建nums2并且要把nums的元素复制到nums2当中
2、终止条件
3、从中分两份分别归并
4、合并这两份
5、注意nums与nums2的方向问题
public void sortImpl(int[] nums, int start, int end) { // TODO Auto-generated method stub int len = end - start + 1; int[] nums2 = new int[len]; System.arraycopy(nums, start, nums2, start, len); mergeSort(nums2,nums,start,end); } public void mergeSort(int[] nums, int[] nums2, int start, int end) { if(end==start) { //nums2[start]=nums[start]; return; } int mid = (start+end)/2; mergeSort(nums2, nums, start, mid); mergeSort(nums2, nums, mid+1, end); combineMergeSort(nums, nums2, start, mid, end); } public void combineMergeSort(int[] nums, int[] nums2, int start, int mid, int end) { int m = start; int n = mid + 1; int s = n; int t = end + 1; int j = m; while(m<s&&n<t) { if(nums[m]<=nums[n]) { nums2[j++] = nums[m++]; }else { nums2[j++] = nums[n++]; } } while(m<s) { nums2[j++] = nums[m++]; } while(n<t) { nums2[j++] = nums[n++]; } }
9、树形选择排序(锦标赛排序)(选择排序)
public void treechoosesort(int[] nums) { int len = nums.length; if(len<=1) { return; } //需要构造的二叉树的高度 int h = (int)Math.ceil(Math.log(len)/Math.log(2))+1; int k = (int)Math.pow(2, h)-1;//需要构造的数组的大小 int[] temps = new int[k]; int m = (int)Math.pow(2, h-1)-1;//1~h-1层的元素的个数总和 int m1=m; for(int i=0;i<len;i++) { temps[m1++] = nums[i]; } for(int i=m1;i<k;i++) { temps[i] = Integer.MAX_VALUE; } for(int n=0;n<len;n++) { m1=m; while(m1!=0) { for(int i=m1;i<k;i+=2) { temps[i/2] = temps[i]>temps[i+1]?temps[i+1]:temps[i]; } m1/=2; } nums[n] = temps[0]; m1=0; for(int i=1;i<h;i++) { if(temps[2*m1+1]==temps[0]) { m1 = 2*m1+1; }else { m1 = 2*m1+2; } } temps[m1]=Integer.MAX_VALUE; } }
10、表插入排序
public void biaoinsertsort(int[] nums) { int len = nums.length; if(len<=1) { return; } int[] temps = new int[len]; int[] nums2 = new int[len]; for(int i=0;i<len-1;i++) { temps[i] = i+1; } temps[len-1]=-1;//记录链表尾 int head=0;//记录链表头 int prev = 0;//记录已排序链表的最后一个元素的下标 int j =0;//用来遍历已排序的链表 int t=0; for(int i=1;i<len;i++) { j=head; while(j!=i) { if(nums[j]>nums[i]) { temps[i] = j; if(j==head) { head=i; }else { temps[t] = i; } if(i+1!=len) { temps[prev]=i+1; }else { temps[prev]=-1; } break; } t=j; j=temps[j]; } if(i==j) { prev=i; } } //已经形成列表,下面就是把它按顺序放置在数组中 t=head; j=0; while(t!=-1) { nums2[j++]=nums[t]; t=temps[t]; } for(int i=0;i<len;i++) { nums[i]=nums2[i]; } }
11、计数排序
public void jishusort(int[] nums) { int len = nums.length; int k = 100; int[] temps = new int[k+1]; for(int i=0;i<len;i++) { temps[nums[i]]+=1; } int sum=0; int t=0; for(int j=0;j<k;j++) { if(temps[j]!=0) { for(int i=0;i<temps[j];i++) { nums[t++] = j; } } } }
12、基数排序
(2)、LSD从个位开始,n为数组中数的最大位数
public void cnsort(int[] nums,int n) { int len = nums.length; if(len<=1) { return; } int t = 0; int m = 1; List<Integer>[] buckets = new List[10]; for(int i=0;i<10;i++) { buckets[i] = new ArrayList<Integer>(); } for(int k=0;k<n;k++) { for(int i=0;i<len;i++) { buckets[nums[i]/m%10].add(nums[i]); } t=0; for(int i=0;i<10;i++) { for(Integer j:buckets[i]) { nums[t++] = j; } buckets[i].clear(); } m *=10; } }
(2)、MSD从高位开始,需要用到递归
13、桶排序
桶中数组采用插入法排序
基数排序就是基于桶排序的,只是基数排序只需要10个桶
算法总结:
参考文献
算法总结:https://blog.csdn.net/hellozhxy/article/details/79911867
堆排序:https://www.cnblogs.com/chengxiao/p/6129630.html
归并排序:https://www.cnblogs.com/chengxiao/p/6194356.html
快速排序:https://www.cnblogs.com/chengxiao/p/6262208.html
表插入排序:https://www.cnblogs.com/ciyeer/p/9075303.html
计数排序:https://www.cnblogs.com/zfdd/p/8034485.html
基数排序:https://blog.csdn.net/u011948899/article/details/78027838