复杂度表:
冒泡排序、插入排序、选择排序
快排、归并排序、堆排序
希尔排序、桶排序、
(不稳定:选择排序、快排、堆排序)
463.Sort Integer 整数排序:http://www.lintcode.com/en/problem/sort-integers/
1.冒泡排序
两两比较,每趟把最大的数移到最后;
(外循环,趟数:n-1趟 [0,n-1);
内循环,有序区趟数,n-1-i;
比较:[j]>[j+1]则swap;)
1 public void sortIntegers(int[] a) { 2 int n = a.length; 3 for (int i = 0; i < n - 1; i++) { 4 for (int j = 0; j < n - i - 1; j++) { 5 if (a[j] > a[j + 1]) { 6 int tmp = a[j]; 7 a[j] = a[j + 1]; 8 a[j + 1] = tmp; 9 } 10 } 11 } 12 }
2.插入排序
取出无序区的第一位作为tar,在有序区里从后向前遍历,大于tar则后移;最后把tar值放到最终位置;
(由于需要j定位;所以:1.j需要定义在外部;2.判断条件在for循环括号内部而不是if语句;)
(定义j;外循环:无序区的长度/趟数,[1,n)
定义tar;内循环:[i,0)后序遍历,条件j>0且tar<[j-1];
后移:[j]=[j-1];定位:a[j] = tar;)
1 public class Solution { 2 public void sortIntegers(int[] a) { 3 int n = a.length; 4 int j; 5 for (int i = 1; i < n; i++) { 6 int tar = a[i]; 7 for (j = i; j > 0 && tar < a[j - 1]; j--) { 8 a[j] = a[j - 1]; 9 } 10 a[j] = tar; 11 } 12 } 13 }
3.选择排序
每趟从无序区选择最小的值放入有序区的末尾;
(外循环:n-1趟,[0,n-1); 其中i指向有序区的后一位;
内循环:扫描无序区 [i+1,n);
判断:[i]>[j]则swap)
1 public class Solution { 2 //选择排序 3 public void sortIntegers(int[] a) { 4 int n = a.length; 5 for (int i = 0; i < n - 1; i++) { 6 for (int j = i + 1; j < n; j++) { 7 if (a[i] > a[j]) { 8 int tmp = a[i]; 9 a[i] = a[j]; 10 a[j] = tmp; 11 } 12 } 13 } 14 } 15 }
4.快速排序
每次排序确定一个数的位置。比该数小的移到左边,大的移到右边。
(例:6-3-7-4-1;lo,hi;pivot为6;注意pivot是值,不是位置;
首先判断hi<6,那么把1移到lo,即1(lo)-3-7-4-1(hi);
判断lo<6,lo++,即1-3-7(lo)-4-1(hi);
此时lo>6,跳出left-while循环,把7移到hi,此时1-3-7(lo)-4-7(hi);可以看到,每次移动都会把上一个移动过的重复的数字覆盖掉。
继续大while循环: hi>6,hi--,1-3-7(lo)-4(hi)-7;hi<6,把4移动到lo,1-3-4(lo)-4(hi)-7,right-while循环后,lo和hi重合,跳出while循环;
最后再把pivot放到该位置上[lo]=pivot;并且return 该位置lo;
这样就完成一轮排序;此时6的位置确定,左右分别为小数和大数)
(1.主程序:sort(a, 0, len-1);
2.sort函数:sort(A[], lo, hi),首先判断lo>=hi则return;partition函数;递归;
3.partition函数:记录pivot;while(<)循环;right-while:判断右侧(&&>),大于则--;否则移动到lo; left-while(&<),小于则++;否则移动到hi;
4.pivot放到最终位置;返回index-lo;)
(注意partition内部的while循环一定要加上=key!!否则错误!)
1 public class Solution { 2 public void sortIntegers(int[] a) { 3 sort(a, 0, a.length - 1); 4 } 5 public int partition (int[] a, int lo, int hi) { 6 int key = a[lo]; 7 while (lo < hi) { 8 while (lo < hi && a[hi] >= key) hi--; 9 a[lo] = a[hi]; 10 while (lo < hi && a[lo] <= key) lo++; 11 a[hi] = a[lo]; 12 } 13 a[lo] = key; 14 return lo; 15 } 16 public void sort(int[] a, int lo, int hi) { 17 if (lo >= hi) return; 18 int index = partition(a, lo, hi); 19 sort(a, lo, index - 1); 20 sort(a, index + 1, hi); 21 } 22 }
5.堆排序
6.归并排序
将若干个有序数组合并成一个有序数组称为归并。
过程:先将数组分成若干小数组并排序,再两两归并成有序数组
(1.主程序-调用mergeSort(a,low,high);
2.helper1:mergeSort-当low<high时左右递归,将数组拆成单个元素;归并merge(a, low, mid, high);
3.helper2:merge-a.tmp数组, 左右指针和k指针; b.当left<=mid和right<=high时,将left和right中小的数保存的tmp中;
4.while()保存剩余的数;
5.for(0,tmp.length)覆盖a[i+low]数组)
1 public class Solution { 2 /** 3 * @param A an integer array 4 * @return void 5 */ 6 public void sortIntegers(int[] a) { 7 // Write your code here 8 mergeSort(a, 0, a.length - 1); 9 } 10 public void merge(int[] a, int low, int mid, int high) { 11 int[] temp = new int[high - low + 1]; 12 int left = low;// 左指针 13 int right = mid + 1;// 右指针 14 int k = 0; 15 // 把较小的数先移到新数组中 16 while (left <= mid && right <= high) { 17 if (a[left] < a[right]) { 18 temp[k++] = a[left++]; 19 } else { 20 temp[k++] = a[right++]; 21 } 22 } 23 // 把左边剩余的数移入数组 24 while (left <= mid) { 25 temp[k++] = a[left++]; 26 } 27 // 把右边边剩余的数移入数组 28 while (right <= high) { 29 temp[k++] = a[right++]; 30 } 31 // 把新数组中的数覆盖nums数组 32 for (int i = 0; i < temp.length; i++) { 33 a[i + low] = temp[i]; 34 } 35 } 36 37 public void mergeSort(int[] a, int low, int high) { 38 int mid = (low + high) / 2; 39 if (low < high) { 40 // 左边 41 mergeSort(a, low, mid); 42 // 右边 43 mergeSort(a, mid + 1, high); 44 // 左右归并 45 merge(a, low, mid, high); 46 } 47 48 } 49 }
参考:归并排序