算法思想--分治法

时间:2022-07-23 11:08:52

分治的基本概念:把一个任务,分成形式和原任务相同,但规模更小的几个部分任务(通常是两个部分),分别完成,或只需要选一部分完成。然后再处理完成后的这一个或几个部分的结果,实现整个任务的完成。

例题:归并排序

数组的排序可以先把前一半排序,在把后一半排序,然后把两半归并到一个新的有序数组,然后再拷贝到原数组,排序完成。

思考:将前一半排序时又要将这一半分成前一半和后一半进行排序,即利用递归的思想进行排序,假设数组的前一半和后一半在原数组内已经排号序了,将两个排号序的数组序列合并一起即可(要求合并后的数组仍是排好序的),这时需要另一个数组当中介。
public void mergesort(int a[],int s,int e,int tmp[]) {
		if(s==e) {
			return;
		}
		if(s<e) {	
		int mid=s+(e-s)/2;
		mergesort(a,s,mid,tmp);
		mergesort(a,mid+1,e,tmp);
		merge(a,s,mid,e,tmp);
	}
	}
	public void merge(int a[],int s,int mid,int e,int tmp[]) {
		int pb=0;
		int p1=s; int p2=mid+1;
		while(p1<=mid&&p2<=e) {
			if(a[p1]<a[p2]) {
				tmp[pb++]=a[p1++];
			}
			else tmp[pb++]=a[p2++];
		}
		
		while(p1<=mid) {
			tmp[pb++]=a[p1++];
		}
		while(p2<=e) {
			tmp[pb++]=a[p2++];
		}
		for(int i=0;i<e-s+1;i++) {
			a[s+i]=tmp[i];
		}
	}
收获:书写程序时  tmp[pb++]=a[p1++];  这样书写更简明扼要,我们利用递归时一定要考虑好回归条件,即使什么都不用返回,也要考虑回归条件,在进行数组的一系列操作时我们应该充分学会利用指针,通过指针实现数组内数的传递

快速排序:

定义:(1)设k=a[0],将k放到适当位置,使的比k小的都在k左边,比k大的都在k右边,和k相等的,在k左右都可
          (2)把k右边快速排序,把k左边快速排序
public void mergesort(int a[],int s,int e) {
		if(s>=e) {
			return;
		}
		int k=a[s];
		int i=s;
		int j=e;
	//一开始是比较看k右边的是不是比k大,不满足的话a【i】和a【j】交换位置,交换后a【j】变成了k,就看
	//k左边的是不是比k小,不是的话交换位置,循环停止的条件是i==j这时所有的元素已经判断完毕		
		
		while(i!=j) {
				while(j>i&&a[j]>=k) {
				
					--j;		
				}
				int m=a[j];
				a[j]=a[i];
				a[i]=m;
				while(i<j&&a[i]<=k) {
					
					++i;
					
				}
				int p=a[j];
				a[j]=a[i];
				a[i]=p;
		}
		
    mergesort(a,s,i-1);
	//进行完上面的操作后a[i]=k;在将i右面的和i左边的进行快速排序即可,所有的元素的左边都比自己大,右边比自己小
	//就实现了排序	
	mergesort(a,i+1,e);
		
			}
这跟课程中的程序有些不同,因为c语言中,可以通过调用方法实现数组中两个数的交换,但是java语言不行。

收获:又提供了一种将数组排序的方法