快速排序:冒泡的进化版,根据某一值key, 将大于key 的往后放,将小于key的往前放;通俗结果就是最后key值左边的比key都小,key值右边的比key都大;在对两侧的序列单独进行key值比较交换,依次类推...
代码的实现与理解:
int a[] = {5, 3, 4, 8, 9, 1, 7, 0, 2, 6};
sort(a, 0, a.length - 1);
for (int h = 0; h < a.length; h++) {
Log.i("chy1234", "==结果数据===" + a[h]);
}
/*********************************************************************/
private void sort(int a[], int leftBound, int rightBound) {
if (leftBound >= rightBound) {
// 如果左节点 >= 右节点, 说明此次遍历结束
return;
}
// 获取第一轮快排后的key 的位置
int mid = partition(a, leftBound, rightBound);
// 针对前半段进行快速排序
sort(a, leftBound, mid-1);
// 针对后半段进行快速排序
sort (a, mid +1, rightBound);
}
/********************************************************************/
/**
* 快排处理
*
* @param a
* @param leftBound
* @param rightBound
* @return 返回排完之后key的位置
*/
private int partition(int a[], int leftBound, int rightBound) {
int pivot = a[leftBound]; // 设定key值为左边第一个值
int left = leftBound + 1; // 从左边第二个位置开始
int right = rightBound; // 尾结点
/**
* 循环结束点===>当左节点大于等于右节点则结束循环
*
* 关于 left = right 情况的解释:(本人对于这个比较迷惑,所以记录一下)
* 当存在数列中仅有两个数比较时,例如leftBound = 0, rightBound = 1 ;
* 会出现上面的 left = right;
* 例如(5, 3)比较, left = 1, right = 1;
* 不会进入循环,最后与key值交换时,出现的的是 5 和 5 交换,(5, 3)不符合预期效果
* 所以此处循环应该有left = right的情况; 这样以 5 为基准,
* 则left在进入循环后会变成 left = 2;right = 1;
* 这样在最后的 key 值位置校正时,就是 5 与 3 进行交换了,符号预期效果
*
*/
while (left <= right) {
/**
* 先从左边开始遍历数组,找到第一个大于pivot的值,
* 如果有那么此时值为 a[left]
*
* 循环条件: 左节点不能大于右节点 并且 值要比 pivot 小的,
* 才可以继续循环;直到遇到left > right 情况或者
* a[left] > pivot的情况,则循环终止
*/
while (left <= right && a[left] <= pivot) left++;
/**
* 从右边边开始遍历数组,找到第一个小于 pivot 的值,
* 如果有那么此时值为 a[right]
*
* 循环条件: 左节点不能大于右节点 并且 值要比 pivot大的,
* 才可以继续循环;直到遇到left > right 情况或者
* a[right] < pivot的情况,则循环终止
*/
while (left <= right && a[right] >= pivot) right--;
/**
* 如果跳出以上循环的条件不是因为节点关系,那么默认找到了一组最大值和最小值
* 此时需要交换最大值和最小值的位置,以便完成大的放后边,小的放前面的规则
* 如果满足交换条件 left < right 则可知 a[left] > key; a[right] < key
*/
if (left < right) {
int temp = a[left];
a[left] = a[right];
a[right] = temp;
}
}
/**
* 校正 key 的位置
*
* 等待循环结束后,除却第一个值(第一个值被认作key值)
* 后面的数列以某一节点为分界点,分界点前面的都小于key,
* 分界点后边的都大于key;
* 此时需要矫正 key 的位置,把他放到分界点上
* =====分界点的位置在哪里呢?====-----此处代码针对分界点我们依赖于left的位置--------
* 上面外层循环结束的条件是 left > right && a[left] > pivot
* 所以 left 本身的位置应该是(以key为分界点)数列右半部分的第一个值
* 因为这里处理的是key 与 首位进行交换, 所以取 a[left - 1]为 key 的位置
*/
int temp = a[leftBound];
a[leftBound] = a[left - 1];
a[left - 1] = temp;
return left -1;
}
快速排序: