1.归并排序
关键概念:双列表指针,临时数组
-
双列表指针:分别遍历两个有序数组
-
临时数组:暂时保存合并之后的结果
public int[] merge(int[] list1, int[] list2){
int l1 = list1.length;
int l2 = list2.length;
int[] newlist = new int[l1 + l2];
int n = 0;
int m = 0;
int i
while(n < l1 && m < l2){
if(list1[n] > list2[m]){
newlist[index++] = list2[m];
}else{
newlist[index++] = list1[n];
}
}
while(n < l1) newlist[index++] = list1[n];
while(m < l2) newlist[index++] = list2[m];
return newlist;
}
递归版归并排序:自顶向底
public void mergeSort(int[] list, int left, int right){
if(left < right){
int mid = left + (right - left)/2;
mergeSort(list, left, mid);
mergeSort(lsit, mid+1, righr);
merge(list, left, mid, mid + 1, right);
}
}
非递归版归并排序:自底向顶
public void mergeSort2(int[] list, int left, int right){
int n = right - left + 1;
for(int step = 2; step / 2 <= n; step *= 2){//保证结束时,
for(int i = left; i <= right; i += step){
//将区域分为[left, mid] 和[mid +1, right] ,左侧有step/2个元素
int mid = i + step / 2 - 1;
if(mid + 1 <= right){//保证右半个区[mid +1, right]域有数据
merge(list, i, mid, mid + 1, min(i + step - 1,right));
}
}
}
}
2.快速排序
- 把序列按照第一位分成两部分:
public static int partition(int[] list, int left, int right){
int p = (int)(left + Math.random()*(right - left))
swap(list, p, left);
int temp = list[left];
while(left < right){
//小于等于temp的数全部移动到temp的左边
while(left < right && list[right] > temp) right--;
list[left] = list[right];
//大于temp的数全部移动到temp的右边
while(left < right && list[left] <= temp) left++;
list[right] = list[left];
}
list[left] = temp;
return left;
}
- 使用递归排序:
public static void quickSort(int[] list, int left, int right){
if(left < right){
int pos = partition(list, left, right);
quickSort(list, left, pos - 1);
quickSort(list, pos + 1, right);
}
}
3.随机选择算法
核心:寻找第一个数,把列表分为两部分。
//将数据分成两部分的算法,此部分为核心代码
int partition(int[] list, int left, int right){
int p = (int)(left + Math.random() * (right - left));
swap(list, left, p);
int temp = list[left];
while(left < right){
while(left < right && list[right] >= temp)) right--;
list[left] = list[right];
while(left < right && list[left] < temp) left++;
list[right] = list[left];
}
list[left] = temp;
return left;
}
//选择第k大的数,递归写法
int randSelect(int[] list, int left, int right, int k){
if(left == right) return left;
int p = partition(list, left, right);
int M = p - left + 1;//表示p为从left开始的第M大的数
if(M == k){
return p;
}else if(M > k){
return randSelect(list, left, p - 1, k);
}else{
return randSelect(list, p + 1, right, k - M);
}
}
//选择第k大的数,循环写法
int randSelect(int[] list, int k){
int left = 0;
int right = list.length - 1;
while(left < right){
int pos = partition(list, left, right);
if(pos + 1 == k){
return pos;
}else if(pos + 1 > k){
right = pos - 1;
}else{
left = pos + 1;
}
}
return left;
}