算法入门
归并排序
归并排序本身是一个递归的过程,在每一次递归的过程中,将数组分成等长的2部分,然后左边进行递归,然后右边跟着递归,然后进行一个排序,这个排序的过程的前提是左右部分都是有序的,然后左右两边的数据分别从头部进行比较,小的数就存入一个新的数组中,并且相应的位置后退一步,这样下来可以使左右两边的数据全部有序的进入,当有一边的数已经全部进入数组,那么直接把剩下的那边依次放入数组就完成了。
public class mergesort {
/*
* 如何进行归并排序?
* 1.首先传入一个数组,然后我们把他分开2分,然后这2分进行递归,递归到结束的条件就是我们分开后的2分中只有
* 一个元素,然后让这两个元素进行排序,排序的过程是两边的数从头开始比较,并且开辟一个新的数组,小的数先进数组,大的数后进入,
* 当一侧的数据读完后,就将剩余那部分的数全部放入数组,然后在将排好序的数,重新放回最初传进来的数组,一层层递归结束后,就是
* 排好顺序的数了
*
* */
//1.先判断这个数组是否为空或者只有一个元素
//解释一下为什么没有返回值,因为传入的参数是一个数组,我们在排序中会对数组中的
//元素进行排序,所以说传入后,即使不返回,数组也变了
static void mergesort(int[] arr){
if (arr==null||arr.length<=1){
return ;
}
mergesort(arr,0,arr.length-1);
}
//如果不为空就进入正式开始的递归排序,这里传入的参数,第一个是数组,第二个是开始位置,第三个是结束位置
static void mergesort(int[] arr,int start ,int end){
//先声明递归结束的条件
if (start==end){
return ;
}
//如果不是就2分,先找到中间点
int mid = (start+end)/2;
//那么分开的部分进行递归的开始和结束位置分别是start mid 和 min+1 end
mergesort(arr, start, mid);
mergesort(arr,mid+1,end);
//关键在于这个merge,这个merge要怎么写?
merge(arr,start,mid,end);
}
static void merge(int[] arr,int start,int mid,int end){
//传进来了三个参数,然后依次进行归并排序
//首先要有2个指针,分别指向2边的开头,然后比较结束的条件就是任意一方的数读到边界!
int[] newarray = new int[arr.length];
int i = start;
int p1 = start;
int p2 = mid+1;
while((p1<mid+1)&&(p2<end+1)){
//这句话的意思就是两边指针所指向的位置进行比较,如果
//小的一边对数组进行赋值,指针向后移动一位
newarray[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
}
while(p1<mid+1){
newarray[i++] = arr[p1++];
}
while(p2<end+1){
newarray[i++] = arr[p2++];
}
//拷贝回去
for(int j = start;j<=end;j++){
arr[j] = newarray[j];
}
}
public static void main(String[] args) {
int[] arr = new int[]{2,5,4,1};
mergesort(arr);
for (int i : arr) {
System.out.println(i);
}
}
}
快速排序
荷兰国旗问题!
什么是荷兰国旗问题?首先我们先看荷兰国旗
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dF89QdNu-1647951934845)(C:\Users\12473\AppData\Roaming\Typora\typora-user-images\image-20220322185513369.png)]
由三种颜色组成,所以我们今天要研究的就是给定一个数组,和一个数num,对数组进行排序,把大于在这个数的数放在右边,小于这个数的数放在数组左边,等于这个数的数放在中间,当然,在大于和小于的部分,我们不要求有序。
所以我们要思考怎么去做?(要求额外的空间复杂度是O(1)),只能用有限制的几个变量进行操作
首先划分2个边界,一个是小于边界,一个是大于边界,小于边界在数组的最左边,大于边界在数组的最右边,我们根据一下的3条规则进行操作
1.数组从左向右遍历,遇到比num小的数,我们将它与小于边界的数进行交换,然后小于边界向后移动一位,
2.当遇到等于num的数,我们的不进行任何操作,继续遍历
3.当遇到大于num的数,将大于边界所指向的数和它进行交换,然后大于边界向前移动一位。然后这次循环重新进行
终止的条件就是我们遍历的数到达了大于的边界就停止遍历。
public class NetherlandsFlag {
static void partion(int[] array,int a,int b,int nums){
int left = a;
int right= b;
int i = a;
//确定左右边界,可以直接却认为数组的开头和结尾(长度减一)
while (i<=right) {//只要没有到达最大数的边界就一直遍历下去,3种条件
//1.比num小
if (array[i]<nums){
//进行交换操作,交换的对象,当前数和小于边界所指向的数,执行结束后i++,left++
int temp = array[i];
array[i] = array[left];
array[left] = temp;
i++;
left++;
}
//等于num
else if(array[i]==nums){
i++;
}
//大于nums
else{
int temp = array[i];
array[i] = array[right];
array[right] = temp;
right--;
}
}
}
public static void main(String[] args) {
int[] array = new int[]{0,7,8,5,5,9,5,4,5,3};
partion(array,0,array.length-1,5);
for (int i : array) {
System.out.println(i);
}
}
}
快速排序
快速排序就是以荷兰国旗排序为基础,这次只给一个数组,我们进行排序,那么参照荷兰国旗,我们可以首先选取数组最后一个数作为num,然后对数组中的数进行排序,分为,小于,等于,大于三部分,排序之后我们将大于区域的最前面的数和num的位置进行交换,然后以num的左右边界的最后一个数作为nums,进行新一轮的排序,这样递归下来我们最终就可以确定出所有数的正确顺序,每次确定一个数。
public class NetherlandsFlag {
static int[] partion(int[] array,int a,int b,int nums){
int left = a;
int right= b;
int i = a;
//确定左右边界,可以直接却认为数组的开头和结尾(长度减一)
while (i<=right) {//只要没有到达最大数的边界就一直遍历下去,3种条件
//1.比num小
if (array[i]<nums){
//进行交换操作,交换的对象,当前数和小于边界所指向的数,执行结束后i++,left++
int temp = array[i];
array[i] = array[left];
array[left] = temp;
i++;
left++;
}
//等于num
else if(array[i]==nums){
i++;
}
//大于nums
else{
int temp = array[i];
array[i] = array[right];
array[right] = temp;
right--;
}
}
//这里的right永远指向的是下一个未知的数,所以返回最后一个确定的最大值的位置,那么就返回right-1,左边的就是left-1
return new int[]{left-1,right+1};
}
static void quicksort(int[] arr,int start,int end){//最初传递的数组肯定是从0到末尾,首先确定出末尾位置
int num = arr[end];
//然后剩下的部分进行排序,传入数组的起点,重点 和 num
int[] res = partion(arr, start, end - 1, num);//拿到交换的位置
int temp = arr[end];
arr[end] = arr[res[1]];
arr[res[1]] = temp;
//交换完毕,递归左右两边,右边的起点是partion+1 ,左边的起点没返回,
if (res[0]>=start){
quicksort(arr,start,res[0]);
}
if (res[1]<end){
quicksort(arr,res[1]+1,end);
}
}
public static void main(String[] args) {
int[] array = new int[]{0,7,8,5,5,9,5,4,5,3};
quicksort(array,0,array.length-1);
for (int i : array) {
System.out.println(i);
}
}
}