算法:排序

 


 

复杂度表:

 

 

冒泡排序、插入排序、选择排序

快排、归并排序、堆排序

希尔排序、桶排序、

(不稳定:选择排序、快排、堆排序)

 

 


 

 

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     }
View Code

 

参考:为什么冒泡排序最优是O(n)

 


 

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 }
View Code

 


 

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 }
View Code

 


 

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 }
View Code

 


 

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 }
View Code

 参考:归并排序

 


 

posted @ 2017-03-01 18:36  不闻余物  阅读(176)  评论(0)    收藏  举报