数据结构 | 排序问题之快速排序
思想:
“快速排序”的思想很简单,整个排序过程只需要三步:
1
2
3
(1)在数据集之中,选择一个元素作为"基准"(`pivot`)。
(2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。
(3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
举例来说,现在有一个数据集${85, 24, 63, 45, 17, 31, 96, 50}$,怎么对其排序呢?
第一步,选择中间的元素45作为”基准”。(基准值可以任意选择,但是选择中间的值比较容易理解。)
第二步,按照顺序,将每个元素与”基准”进行比较,形成两个子集,一个”小于45“,另一个”大于等于45“。
第三步,对两个子集不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
快速排序算法 QuickSort
1
2
3
4
5
6
7
8
9
void QuickSort(SeqList R,int low,int high)
{ //对R[low..high]快速排序
int pivotpos; //划分后的基准记录的位置
if(low<high){//仅当区间长度大于1时才须排序
pivotpos=Partition(R,low,high); //对R[low..high]做划分
QuickSort(R,low,pivotpos-1); //对左区间递归排序
QuickSort(R,pivotpos+1,high); //对右区间递归排序
}
} //QuickSort
划分算法 Partition
具体做法:
(初始化)设置两个指针 $i$ 和 $j$,它们的初值分别为区间的下界和上界,即 $i=low$,$j=high$; 选取无序区的第一个记录 R[i]
(即 R[low]
)作为基准记录,并将它保存在变量 pivot
中;
令 j 自 high 起向左扫描,直到找到第 1 个关键字小于 pivot.key 的记录 R[j]
,将 R[j]
)移至 i 所指的位置上,这相当于 R[j]
和基准 R[i]
(即 pivot)进行了交换,使关键字小于基准关键字 pivot.key 的记录移到了基准的左边,交换后 R[j]
中相当于是 pivot;
然后,令 i 指针自 i+1 位置开始向右扫描,直至找到第 1 个关键字大于 pivot.key 的记录 R[i]
,将 R[i]
移到 j 所指的位置上,这相当于交换了 R[i]
和基准 R[j]
,使关键字大于基准关键字的记录移到了基准的右边,交换后 R[i]
中又相当于存放了 pivot;
接着令指针 j 自位置 j-1 开始向左扫描,如此交替改变扫描方向,从两端各自往中间靠拢,直至 $i=j$ 时,i便是基准 pivot 最终的位置,将 pivot 放在此位置上就完成了一次划分。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int Partition(SeqList R,int i,int j)
{//调用Partition(R,low,high)时,对R[low..high]做划分,
//并返回基准记录的位置
ReceType pivot=R[i]; //用区间的第1个记录作为基准 '
while(i<j){ //从区间两端交替向中间扫描,直至i=j为止
while(i<j&&R[j].key>=pivot.key) //pivot相当于在位置i上
j--; //从右向左扫描,查找第1个关键字小于pivot.key的记录R[j]
if(i<j) //表示找到的R[j]的关键字<pivot.key
R[i++]=R[j]; //相当于交换R[i]和R[j],交换后i指针加1
while(i<j&&R[i].key<=pivot.key) //pivot相当于在位置j上
i++; //从左向右扫描,查找第1个关键字大于pivot.key的记录R[i]
if(i<j) //表示找到了R[i],使R[i].key>pivot.key
R[j--]=R[i]; //相当于交换R[i]和R[j],交换后j指针减1
} //endwhile
`R[i]`=pivot; //基准记录已被最后定位
return i;
} //partition
冒泡排序
对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。就好像一串气泡一样,最终从小到大或从大到小依次排下来。
代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.util.Arrays;
public class BubbleSort {
public static void sort(int[] arr) {
int len = arr.length;
int tmp;
System.out.println("原始顺序: "+ Arrays.toString(arr));
//i表示第几趟排序
for (int i = 1; i < len; i++) {
//每次都从最后一个开始,知道第len-1趟排序
for (int j = len - 1; j > i-1; j--) {
//如果后面的比前面的小,就像泡泡一样冒上去
if (arr[j] < arr[j - 1]) {
tmp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = tmp;
}
}
System.out.println("第"+i+"趟排序: "+ Arrays.toString(arr));
}
}
public static void main(String[] args) {
int[] arr = new int[10];
//初始化数组
for (int i = 0; i < 10; i++) {
arr[i] = (int) (Math.random() * (100 + 1));
}
BubbleSort.sort(arr);
}
}