排序算法
快速排序
是冒泡排序演变而来,基于分治法
即每一轮挑选一个元素,并让其他比它大的元素移动到数列的一边,比它小的元素移动到数列的另一边,从而把数列拆解成两个部分
时间复杂度为O(nlogn)
基准元素的选择
最简单的方式选择数列的第一个元素
但是如果这个元素是该数列的最大值或最小值,则排序时无法将数列拆解成两部分,时间复杂度会退化成O(n^2)
第二个方法是随机选择数列中的元素作为基准元素,但是还是有几率影响分治的效果
具体方法
- 双边循环法
- 单边循环法
双边循环法
1.选定基准元素P,设定两个指针分别指向最左L和最右R的元素
2.第一次循环
从R开始,如果R >= P,R指针左移,否则停止,切换到L指针
从L开始,如果L <= P,指针右移,否则停止
3.L也停止之后,交换L与R的值
4.第二次循环
重新切换到R指针向左移,因为8>4,继续左移,2<4,停在2的位置,切换到L指针向右移
5.L也停止之后,交换L与R的值
6.第三次循环
7.交换元素
8.第四次循环
L指针与R指针重合,移动停止
9.最有把P与重合点的元素进行交换
这一轮宣告结束,P两端的元素分别进行下一轮
代码如下:
public static void quickSort(int[] arr, int startIndex, int endIndex)
{
//递归结束
if(startIndex >= endIndex)
{
return;
}
//基准 元素
int pivotIndex = partition(arr, startIndex, endIndex);
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
}
private static int partition(int[] arr, int startIndex, int endIndex)
{
//取第一个位置的元素作为基准元素
int pivot = arr[startIndex];
int left = startIndex;
int right = endIndex;
while(left != right)
{
while(left < right && arr[right] > pivot)
{
right --;
}
while(left < right && arr[left] <= pivot)
{
left ++;
}
if(left < right)
{
int p = arr[left];
arr[left] = arr[right];
arr[right] = p;
}
}
arr[startIndex] = arr[left];
arr[left] = pivot;
return left;
}
单边循环法
1.选定基准元素P,同时设置一个M指针代表小于基准元素的区域边界
2.从左到右遍历
如果遍历到的元素 > P,则继续往后遍历
如果遍历到的元素 < P,则将M指针右移,并且将遍历到的元素和M指针所在位置的元素交换位置
3.遍历到5,5 > 4,继续遍历
4.遍历到6,6 > 4,继续遍历
5.遍历到2,2 < 4,M指针右移,并交换元素
6.遍历到8,8 > 4,继续遍历
7.遍历到1,1 < 4,M指针右移,并交换元素
8.最后交换P和M
这一轮宣告结束,M两端的元素分别进行下一轮
代码如下:
public static void quickSort(int[] arr, int startIndex, int endIndex)
{
if(startIndex >= endIndex)
{
return;
}
int pivotIndex = partition(arr, startIndex, endIndex);
quickSort(arr, startIndex, pivotIndex - 1);
quickSort(arr, pivotIndex + 1, endIndex);
}
privat static int partition(int[] arr, int startIndex, int endIndex)
{
int pivot = arr[startIndex];
int mark = startIndex;
for(int i = startIndex + 1; i <= endIndex; i ++)
{
if(arr[i] < pivot)
{
mark ++;
int p = arr[mark];
arr[mark] = arr[i];
arr[i] = p;
}
}
arr[startIndex] = arr[mark];
arr[mark] = pivot;
return mark;
}