- 1.快排
分治:先定数值x,再利用数值比较进行递归排序
原地排序,比较节省空间。
1.快排:分治
一层一层的分开使用相同的方法进行
java:
import java.io.IOException;
import java.util.Scanner;
public class 快排 {
//分治法进行排序操作,注意边界问题
public static int[] quicksort2(int[] A,int l,int r){
//判断边界,如果就一个数据
if(l>=r){return A;}
//记录一个x数据,进行比较
int m = l+r >>1;
int x = A[m];
int i=l-1;
int j=r+1;
//更换变量进行
while (i<j){
do i++;while (A[i]<x);
do j--;while (A[j]>x);
if(i<j){
int temp = A[i];
A[i] = A[j];
A[j] = temp;
}
}
//已经分成了两块
quicksort(A,l,j);//左边排好,再去右边,右边已经变成了j;
quicksort(A,j+1,r);
return A;
}
public static void main(String[] args) throws IOException {
//使用buffersort更快
//BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));//先创建缓冲区,再说明是输入数据
Scanner sc= new Scanner(System.in);
//读入数据,数据都是String-要进行转换成整形
int N= sc.nextInt();
int[] A = new int[N];
//pai-转换
for(int i=0;i<N;i++){
//String b = buf.readLine();
A[i] = sc.nextInt();
}
//快速排序-数组
quicksort2(A,0,N-1);//注意是N-1
for(int i=0;i<N;i++){
System.out.print(A[i]+" ");
}
}
}
c++代码比较简洁
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l + r >> 1];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
}
quick_sort(q, l, j), quick_sort(q, j + 1, r);
- 归并排序-先定位置,位置订好了,利用位置进行递归排序,再进行两边的合并
- olongn–longn层
-需要额外的辅助数组进行排序
-
trick:
先定义数组,再进行使用会节省非常多的时间,所以先声明
static int[]
package 大学菜;
import java.util.Scanner;
public class 归并 {
//与快排相比,要开辟新的空间进行使用。
//先定好一个位置,根据位置两边排序,然后进行合并
static int N = 100010;
static int[] temp = new int[N];
public static int[] mergesort(int[] A,int l,int r){
//先看边界
if(l>=r){return A;}
//定位置
int middle = l+r>>1;
//mersort
mergesort(A,l,middle);
mergesort(A,middle+1,r);
//下面才是递归中内容,递归几次,后面return几次
//开辟新的空间数组
int k=0;//新数组的下标
int i =l;//递归时的左边的边界l
int j = middle+1;//递归时右边的边界j
while (i<=middle && j<=r){//说明两边同时是满足边界 要求饿的
//两边同时比较
if(A[i]<=A[j]){temp[k] = A[i];i++;k++;}
else {temp[k] = A[j];k++;j++;}
}
//如果有剩余的部分ze续接在后面
while (i<=middle){temp[k++] = A[i++];}
while (j<=r){temp[k++] = A[j++];}
for (i = l, j = 0; i <= r; i ++, j ++ ) A[i] = temp[j];//每次都是一个分治中的一层
return A;
}
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int N = sc.nextInt();
int[] A = new int[N];
for(int i=0;i<N;i++){
A[i] = sc.nextInt();
}
int[] B = mergesort(A,0,N-1);
for(int i=0;i<N;i++){
System.out.print(B[i]+" ");
}
}
}
默写程序-发现-定义数组在外面可以节省时间
import java.util.Scanner;
public class 归并 {
//与快排相比,要开辟新的空间进行使用。
//先定好一个位置,根据位置两边排序,然后进行合并
/*void merge_sort(int q[], int l, int r)
{
if (l >= r) return;
int mid = l + r >> 1;
merge_sort(q, l, mid);
merge_sort(q, mid + 1, r);
int k = 0, i = l, j = mid + 1;
while (i <= mid && j <= r)
if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];
else tmp[k ++ ] = q[j ++ ];
while (i <= mid) tmp[k ++ ] = q[i ++ ];
while (j <= r) tmp[k ++ ] = q[j ++ ];
for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];
}*/
static int N = 100010;
static int[] temp = new int[N];
//额外定义数字
static int M = 100010;
static int[] tmp =new int[M];
public static int[] mergesort(int[] A,int l,int r){
//先看边界
if(l>=r){return A;}
//定位置
int middle = l+r>>1;
//mersort
mergesort(A,l,middle);
mergesort(A,middle+1,r);
//下面才是递归中内容,递归几次,后面return几次
//开辟新的空间数组
int k=0;//新数组的下标
int i =l;//递归时的左边的边界l
int j = middle+1;//递归时右边的边界j
while (i<=middle && j<=r){//说明两边同时是满足边界 要求饿的
//两边同时比较
if(A[i]<=A[j]){temp[k] = A[i];i++;k++;}
else {temp[k] = A[j];k++;j++;}
}
//如果有剩余的部分ze续接在后面
while (i<=middle){temp[k++] = A[i++];}
while (j<=r){temp[k++] = A[j++];}
for (i = l, j = 0; i <= r; i ++, j ++ ) A[i] = temp[j];//每次都是一个分治中的一层
return A;
}
public static void main(String[] args) {
Scanner sc =new Scanner(System.in);
int N = sc.nextInt();
int[] A = new int[N];
for(int i=0;i<N;i++){
A[i] = sc.nextInt();
}
int[] B = sort2(A,0,N-1);
for(int i=0;i<N;i++){
System.out.print(B[i]+" ");
}
}
public static int[] sort2(int[] A, int l,int r){
//第一步,判断边界
if(l>=r){return A;}
//归并核心是先按照位置进行分组,再进行合并操作
//找位置
int mid = l+r >> 1;
//分而治之
sort2(A,l,mid);//左
sort2(A,mid+1,r);//右
//递归到最后一个进行什么操作
//临时数组的下标
int k=0;
//边界赋值
int i = l;
int j = mid+1;
//判断
while (i<=mid && j<=r){
//双指针操作
if(A[i]<A[j]){
tmp[k++]=A[i];
i++;
}
else {
tmp[k++] = A[j];
j++;
}
}
//当上面进行完成后,是否有一部分是多余饿的?
while (i<=mid){tmp[k++] = A[i];i++;}
while (j<=r){tmp[k++] = A[j];j++;}
//此时的tmp已经是赋值好的,将现在的tmo赋值会愿数组
for(k=0,i=l;i<=r;i++,k++){//每次的l和r都是一个递归的过程,则可以原来的tmp数组进行覆盖
A[i]=tmp[k];
}
return A;
}
}