数据结构与算法初学——排序篇02

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43296323/article/details/101694342

一、鸡尾酒排序
鸡尾酒排序是冒牌排序的一个改良版,与冒泡排序相不同的是鸡尾酒排序是运用双指针,一个指针(以下称为start指针)从左向右遍历另一个指针(以下称为end指针)从右向左遍历,在遍历的过程中,end指针如果遇到比自己大的数,就与他交换位置,把较大的数放在后面,start指针则相反,在遍历过程中,如果遇到比自己小的数就把他交换到前面。经过一次排序后我们可以确保这组数中最大的数在n-1的位置上,而最小的数在0位置上。然后在下一次循环的时候我们就可以不再去考虑这两个数,这样每次减少需要排序的两个数,就可以节省很多时间,同时这种节省后的排序方法很像一杯鸡尾酒的形状,所以也被称之为——鸡尾酒排序。
下面我们用{3,1,6,5,4,7}这组数据来模拟一下,此时我们的start→3,end→7
第一次——1,3,6,5,4,7
第二次——1,3,4,5,6,7
排序完成。下面是代码实现

public class jiweijiuSort {
	public static void main(String args[]) {
		int a[] = {3,1,6,5,4,7};
		sort(a);
		for(int i=0;i<a.length;i++)
		{
			System.out.println(a[i]);
		}
	}

	private static void sort(int[] a) {

		int start=0;
		int end = a.length-1;
		while(start<end) {
			
			for(int j=end;j>start;j--)
			{
				if(a[j]<a[j-1])
				{
					swap(a,j,j-1);
				}
			}
			
			for(int j=start;j<end;j++)
			{
				if(a[j]>a[j+1])
				{
					swap(a,j,j+1);
				}
			}
			start++;
			end--;
			
		}
	}
	public static void swap(int []a,int b,int c) {
		int temp;
		temp = a[b];
		a[b] = a[c];
		a[c] = temp;
	}

二、希尔排序
希尔排序是插入排序的一个改良版,希尔排序通过把一个长度较大大的数组,拆分成若干个长度较小数组,然后对小数组进行插入排序,然后使得小数组有序,进而使得大数组有序。当然我们在拆分的过程中,不可能真正的把它拆分成几个小的数组,我们只是用到这样的想法而已,我们通过设立一个分组数gap,通过跳跃取值,来实现数组元素的分组比较,在比较的过程中运用插入排序,然后经过多次小数组合并使得数据整体有序
下面为代码实现

public class ShellSort {

	public static void main(String args[]) {
		int[] a = {3,1,6,5,4,7};
		sort(a);
		for(int i=0;i<a.length;i++)
		{
			System.out.println(a[i]);
		}
		
	}
	public static void sort(int[] a) {
		int temp;
		int gap = a.length;
		while(gap>1) {
			gap=gap/2;
			
			for(int i=gap;i<a.length;i++)
			{
				for(int j=i;j>= gap && a[j]<a[j-gap];j-=gap) {
					
					swap(a,j,j-gap);
				}
			}
			
		}
	}
	private static void swap(int[] a, int b, int c) {
		
		int temp;
		temp = a[b];
		a[b] = a[c];
		a[c] = temp;
		
	}
}

三、快速排序(填坑法)与快速排序(双指针法)
(1)双指针法
快速排序是一种十分实用的排序方法,首先,我们需要设立一个基准值pivot(通常情况下我们会把数组的第一个元素设立为基准值),以及两个分别从左右遍历数组的指针left和right,设立i从left开始从左往右遍历,j从right开始从右往左遍历,当i遇到比基准值大的数时就停下,当j遇到比基准值小的数的时候也停下,然后交换i和j的值,此时自i指向的数前面的数组元素,都小于基准值,自j以后包括j指向的数组元素都大于基准值,因为我们的a[0]已经被pivot暂存,所以我们可以吧a[i]的值赋给a[0],然后把pivot的值赋给a[i],这样既保证了基准值两侧得数全都大于或小于基准值,并且整个数组内数据完整,没有缺少,这就是一轮排序需要做的事情,然后我们再通过递归再次调用本身,分别对基准值左右两侧的数据分别再次进行排序。
下面是代码实现

public class kuaisuSort {

	public static void main(String args[]) {
		int[] a = {3,1,6,5,4,7};
		sort(a,0,a.length-1);
		for(int i=0;i<a.length;i++) {
			System.out.println(a[i]);
		}
	}

	private static void sort(int[] a,int left,int right) {
		
		if(left>right) {
			return;
		}
		int pivot = a[left];
		int i = left;
		int j = right;
		while(i!=j) {
			
			while(a[j]>= pivot && i<j) {
				j--;
			}
			while(a[i]<= pivot && i<j) {
				i++;
			}
			swap(a,i,j);
		}
		a[left] = a[i];
		a[i] = pivot;
		sort(a,left,i-1);
		sort(a,j+1,right);
	}
	
	public static void swap(int []a,int b,int c) {
		int temp;
		temp = a[b];
		a[b] = a[c];
		a[c] = temp;
	}
}

(2)填坑法
填坑法与双指针法的大概情况基本相同,主要不同的地方就在于双指针法采用的是数交换的方法,而填坑法则是采用数值覆盖。下面是代码实现

public class kuaisuSorttiankeng {

	public static void main(String args[]) {
		int[] a = {4,1,6,5,3,7};
		sort(a,0,a.length-1);
		for(int i=0;i<a.length;i++) {
			System.out.println(a[i]);
		}
	}

	private static void sort(int[] a,int left,int right) {
		
		if(left>=right) {
			return;
		}
		int pivot = a[left];
		int i = left;
		int j = right;
		while(i!=j) {
			
			while(a[j]>= pivot && i<j) {
				j--;
			}
			a[i] = a[j];
			while(a[i]<= pivot && i<j) {
				i++;
				
			}
			a[j] = a[i];
		}
		a[j] = pivot;
		sort(a,left,i-1);
		sort(a,j+1,right);
	}
}

这里划重点
填坑法的赋值运算一定要放在循环外面,切记切记切记!!!

while(a[j]>= pivot && i<j) {
				j--;
			}
			a[i] = a[j];
			while(a[i]<= pivot && i<j) {
				i++;
				
			}
			a[j] = a[i];

就比如这里的赋值,如果在循环里面进行的话就会出现i和j数据位置的错误,导致数组元素丢失,所以一定要在循环外面赋值!

猜你喜欢

转载自blog.csdn.net/weixin_43296323/article/details/101694342
今日推荐