排序算法之快速排序(包含hover法、挖坑法、前后指针)详解

简介:快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。


  其基本思想为:任取待排序元素序列中 的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右 子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。
  因为快速排序采用了分治算法的思想,所以排序速率相对较快。


正文

  下面叙述一下快速排序的思想:
  第一步:选择一个基准值。(选择方法很多,目前选择数列里最后一个作为基准值的方法。)

在这里插入图片描述
  第二步:遍历整个区间,把所有的数和基准值作比较,并进行数据移动,使得
        ①比基准值小的数,放到基准值的左边
        ②比基准值大的数,放到基准值的右边
在这里插入图片描述
  第三步:采用分治算法,将整个区间分为三个部分:[left, div - 1], [div], [div + 1, right].
此处采用递归的方法来实现分治算法,递归的终止条件就是:
                ①小区间的size == 0
                ②小区间的数已经有序,也就是只有一个元素的时候。


接下来就是重头戏了,将数组分为三部分有三种方法:

1、hover法:
流程:
在这里插入图片描述
在这里插入图片描述
具体进行过程如下:

在这里插入图片描述
代码如下:

int Partition_1(int arr[], int left, int  right){//hover法    
	int begin = left;    
	int end = right;    
	while (begin < end){         
		while (begin < end && arr[begin] <=  arr[right]){             
			begin++;         
		}         
		while (begin < end && arr[end] >=  arr[right]){             
			end--;         
		}         
		Swap(arr + begin, arr + end);    
	}    
	Swap(arr + begin, arr + right);    
	return begin;
}

2、挖坑法:
流程:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
代码如下:


int Partition_2(int arr[], int left, int right){   //挖坑法    
	int begin = left;    
	int end = right;    
	int pivot = arr[right];    
	while (begin < end) {         
		while (begin < end && arr[begin] <=  pivot){             
			begin++;         
		}         
		arr[end] = arr[begin];         
		while (begin < end && arr[end] >= pivot){             
			end--;         
		}         
		arr[begin] = arr[end];    
	}    
	arr[begin] = pivot;    
	return begin;
}

3、前后下标法
流程:
  第一步:先用两个下标 div,i 指向数列的第一个元素,取最后一个元素作为基准值。
在这里插入图片描述
  第二步:遍历整个数列,让 i 下标的值依次与基准值进行比较,如果小于等于基准值,那么交换div 和 i 所在值,并且 div 和 i 都向后移动,如果大于基准值,只让 i 向后移动即可,当整个数列遍历完后,将 div 所在值与基准值进行交换即可。此时的 div 就是中间位置。下面是遍历的流程。
在这里插入图片描述
代码如下:


int Partition_3(int arr[], int left, int right){  //前后下标    
	int div = left;    
	for (int i = left; i < right; i++){         
		if (arr[i] < arr[right]){             
			Swap(arr + i, arr + div);             
			div++;         
		}    
	}    
	Swap(arr + div, arr + right);    
	return div;
}


快速排序完整代码如下:


int Partition_1(int arr[], int left, int  right){//hover法    
	int begin = left;    
	int end = right;    
	while (begin < end){         
		while (begin < end && arr[begin] <=  arr[right]){             
			begin++;         
		}         
		while (begin < end && arr[end] >=  arr[right]){             
			end--;         
		}         
		Swap(arr + begin, arr + end);    
	}    
	Swap(arr + begin, arr + right);    
	return begin;
}
int Partition_2(int arr[], int left, int right){   //挖坑法    
	int begin = left;    
	int end = right;    
	int pivot = arr[right];    
	while (begin < end) {         
		while (begin < end && arr[begin] <=  pivot){             
			begin++;         
		}         
		arr[end] = arr[begin];         
		while (begin < end && arr[end] >= pivot){             
			end--;         
		}         
		arr[begin] = arr[end];    
	}    
	arr[begin] = pivot;    
	return begin;
}
int Partition_3(int arr[], int left, int right){  //前后下标    
	int div = left;    
	for (int i = left; i < right; i++){         
		if (arr[i] < arr[right]){             
			Swap(arr + i, arr + div);             
			div++;         
		}    
	}    
	Swap(arr + div, arr + right);    
	return div;
}
void __QuickSort(int arr[], int left, int right){    
	if (left == right){         
		//区间内只有一个数         
		return;    
	}    
	if (left > right){         
		//区间内没有数         
		return;    
	}    
	//基准值是 arr[right]    
	int div;  
	//用来保存最终基准值所在的下标    
	div = Partition_3(arr, left, right); 
	//遍历arr[left, right],把小的放左,大的放右,返回最后基准值所在的下标    
	//此时区间被分成了 
	//[left, div - 1] 比基准值小  [div, div]基准值  [div + 1, right]比基准值大    
	__QuickSort(arr, left, div - 1);    
	__QuickSort(arr, div + 1, right);
}
void QuickSort(int arr[], int size){   
 	__QuickSort(arr, 0, size - 1);
 }

猜你喜欢

转载自blog.csdn.net/Code_beeps/article/details/88432208
今日推荐