1 package sort;
2
3 /**
4 * 数组的各种排序操作
5 * Created by liuwei on 16/3/6.
6 */
7 public class MSort {
8
9 /**
10 * 直接插入排序
11 * 外层一个循环,从第2个元素开始(下标为1),遍历后面的所有元素
12 * 内层一个循环,从当前位置position =i 开始,每次与position-1的元素对比
13 * 如果当前元素小于position-1的元素,position--
14 * 如果当前元素大于等于position-1的元素,说明position就是我们要插入的地方
15 * 内层循环的中止条件:因为我们每次都是与position-1做对比的,显然position>=1
16 *
17 * check下:
18 * 当position==1的时候,进入while循环,
19 * 如果当前元素大于等于下标为0的元素,直接break position=1
20 * 如果当前元素小于下标为0的元素,position-- position=0 然后不满足循环条件,退出
21 * */
22 public static void straightInsertionSort(int[] nums){
23 if(nums == null) return;
24 for(int i=1; i < nums.length; i++){
25 int position = i;
26 while(position >=1){
27 if(nums[i] < nums[position - 1]){
28 position --;
29 }
30 else{
31 break;
32 }
33 }
34 int tmp = nums[i];
35 for(int j = i; j>position;j--){
36 nums[j] = nums[j-1];
37 }
38 nums[position] = tmp;
39 }
40 }
41
42 /**
43 * 冒泡排序
44 * 冒泡排序每次将最大的沉到最后面,每次确定一个最大的,
45 * 因此,在内层循环的时候,每次实际需要遍历的个数-1
46 * */
47 public static void bubbleSort(int[] nums){
48 if(nums == null) return;
49 for(int i=1; i < nums.length; i++){
50 for(int j = 0; j < nums.length - i; j++ ){
51 if(nums[j] > nums[j+1]){
52 int tmp = nums[j];
53 nums[j] = nums[j+1];
54 nums[j+1] = tmp;
55 }
56 }
57 }
58 }
59
60 /**
61 * 快速排序
62 * 快排的基本思想是选择一个标杆元素,将比标杆元素大的放置在它的后面,将比它小的放在它前面
63 * 这样,我们就把原先的数组分成两部分,左边那部分全部比标杆元素小,右边那部分全部比标杆元素大
64 * 这样,我们只要递归的处理左右两部分即可
65 * */
66 public static void quickSort(int[] nums,int left,int right){
67 if(left < right){
68 int flag = partition(nums,left,right);
69 quickSort(nums,left,flag-1);
70 quickSort(nums,flag+1,right);
71 }
72 }
73
74 private static int partition(int[] nums, int left, int right) {
75 int pivotekey = nums[left];
76 while(left < right){
77 while(left < right && nums[right] >= pivotekey) right --;
78 nums[left] = nums[right];
79 while(left < right && nums[left] <= pivotekey) left ++;
80 nums[right] = nums[left];
81 }
82 nums[left] = pivotekey;
83 return left;
84 }
85
86
87 /**
88 * 选择排序
89 * 简单选择排序的基本思想就是每次选择最大或者最小的放在最后面或者最前面的位置
90 * */
91 public static void simpleSelectionSort(int[] nums){
92 if(nums == null) return;
93 for(int i=1; i < nums.length;i++){
94 int maxIndex = 0;
95 for(int j=0;j <= nums.length - i;j++){
96 if(nums[j] > nums[maxIndex]){
97 maxIndex = j;
98 }
99 }
100 int tmp = nums[maxIndex];
101 nums[maxIndex] = nums[nums.length - i];
102 nums[nums.length - i] = tmp;
103 }
104 }
105
106 /**
107 * 归并排序
108 * 归并排序最本质的思想是利用两个有序数组O(m+n)时间复杂度的合并
109 * 但是,有个前提,必须是有序数组,但是给的肯定只有一个待排序的无序数组,怎么构成有序呢?
110 * 因此,这里就需要划分,当划分成n份,每个小组只有一个元素,这时候,再选出两组,一合并就是有序的了,以此类推
111 * */
112 public static void mergingSort(int[] nums,int left,int right){
113 if(left < right){
114 int mid = left + (right - left) / 2;
115 mergingSort(nums,left,mid);
116 mergingSort(nums,mid+1,right);
117 merge(nums,left,mid,right);
118 }
119 }
120
121 private static void merge(int[] nums, int left, int mid, int right) {
122 int[] tmps = new int[right - left + 1];
123 int i = left,j = mid+1;
124 int k = 0;
125 while(i<=mid && j <=right){
126 if(nums[i] <= nums[j]){
127 tmps[k++] = nums[i];
128 i++;
129 }
130 else{
131 tmps[k++] = nums[j];
132 j++;
133 }
134 }
135 while(i<=mid){
136 tmps[k++] = nums[i];
137 i++;
138 }
139 while(j<=right){
140 tmps[k++] = nums[j];
141 j++;
142 }
143 for(k=left; k<=right; k++){
144 nums[k] = tmps[k - left];
145 }
146 }
147
148 private static void show(int[] nums){
149 for(Integer i : nums){
150 System.out.print(i+" ");
151 }
152 System.out.println();
153 }
154
155 public static void main(String[] args) {
156 int[] nums = {1,3,5,7,9,0,8,6,4,2};
157 // int[] nums = {14,49,38,65,97,76,13,27};
158 // bubbleSort(nums);
159 // straightInsertionSort(nums);
160 // quickSort(nums,0,nums.length-1);
161 // simpleSelectionSort(nums);
162 mergingSort(nums,0,nums.length -1);
163 show(nums);
164 }
165 }