数据结构快排专题
Posted Huang_ZhenSheng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构快排专题相关的知识,希望对你有一定的参考价值。
目录
快排递归:
版本1:左右指针
单趟:
//单趟
int PartSort(int*a, int left, int right)
{
/*int mid = GetMidIndex(a, left, right);
swap(&a[left],&a[mid]);*/
int key = left;
while (left < right)
{
//左边做key,右边先走找小的
while (left < right && a[right] >= a[key])
{
right--;
}
//左边再走,找大
while (left < right && a[left] <= a[key])
{
left++;
}
//交换,把大的换到右边,小的换到左边
swap(&a[left], &a[right]);
}
swap(&a[key],&a[right]);
return right;
}
思考:单趟排完,如何让key左边区间有序,key右边区间有序
--------->类似递归
思路如图:
完整代码:
void swap(int* px, int* py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
//单趟
int PartSort(int*a, int left, int right)
{
int key = left;
while (left < right)
{
//左边做key,右边先走找小的
while (left < right && a[right] >= a[key])
{
right--;
}
//左边再走,找大
while (left < right && a[left] <= a[key])
{
left++;
}
//交换,把大的换到右边,小的换到左边
swap(&a[left], &a[right]);
}
swap(&a[key],&a[right]);
return right;
}
void QuickSort(int* a, int left,int right)
{
if (left < right)
{
int keyi = PartSort(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
PrintSort(a+left, right-left+1);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
}
void TestQuickSort()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
int n = sizeof(a) / sizeof(int);
QuickSort(a, 0, n - 1);
PrintSort(a,n);
}
思考:时间复杂度?
思考:有无什么解决办法能让快排在有序的情况下时间复杂度不是O(N^2)
-------->是由于选key导致的
优化(三数取中):
通过三相取中,使得时间复杂度不会出现最坏的情况
三相取中使得有序的情况一直二分下去,例:1,2,3,4,5,6,7,8,9
//三数取中
int GetMidIndex(int*a, int left, int right)
{
int mid = left + (right - left) / 2;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return left;
}
else
{
return right;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
void swap(int* px, int* py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
//单趟
int PartSort(int*a, int left, int right)
{
int mid = GetMidIndex(a, left, right);
swap(&a[left],&a[mid]);
int key = left;
while (left < right)
{
//左边做key,右边先走找小的
while (left < right && a[right] >= a[key])
{
right--;
}
//左边再走,找大
while (left < right && a[left] <= a[key])
{
left++;
}
//交换,把大的换到右边,小的换到左边
swap(&a[left], &a[right]);
}
swap(&a[key],&a[right]);
return right;
}
void QuickSort(int* a, int left,int right)
{
if (left < right)
{
int keyi = PartSort(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
PrintSort(a+left, right-left+1);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
}
void TestQuickSort()
{
int a[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
int n = sizeof(a) / sizeof(int);
QuickSort(a, 0, n - 1);
PrintSort(a,n);
}
版本2:挖坑法
单趟:
int PartSort2(int* a, int left, int right)
{
int mid = GetMidIndex(a, left, right);
swap(&a[left], &a[mid]);
int key = a[left];
int hole = left;
while (left < right)
{
//右边去找小,填到左边的坑里面
while (left < right && a[right] >= key)
{
right--;
}
//把右边找的小的,填到左边的坑,自己形成新的坑
a[hole] = a[right];
hole = right;
//左边去找大,填到右边的坑里面
while (left < right && a[left] <= key)
{
left++;
}
//把左边找的大的,填到右边的坑,自己形成新的坑
a[hole] = a[left];
hole = left;
}
a[hole] = key;
return hole;
}
完整代码:
//挖坑法
void swap(int* px, int* py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
//三数取中
int GetMidIndex(int*a, int left, int right)
{
int mid = left + (right - left) / 2;
if (a[left] < a[mid])
{
if (a[mid] < a[right])
{
return mid;
}
else if (a[left] > a[right])
{
return left;
}
else
{
return right;
}
}
else
{
if (a[mid] > a[right])
{
return mid;
}
else if (a[left] < a[right])
{
return left;
}
else
{
return right;
}
}
}
int PartSort2(int* a, int left, int right)
{
int mid = GetMidIndex(a, left, right);
swap(&a[left], &a[mid]);
int key = a[left];
int hole = left;
while (left < right)
{
//右边去找小,填到左边的坑里面
while (left < right && a[right] >= key)
{
right--;
}
//把右边找的小的,填到左边的坑,自己形成新的坑
a[hole] = a[right];
hole = right;
//左边去找大,填到右边的坑里面
while (left < right && a[left] <= key)
{
left++;
}
//把左边找的大的,填到右边的坑,自己形成新的坑
a[hole] = a[left];
hole = left;
}
a[hole] = key;
return hole;
}
void QuickSort(int* a, int left, int right)
{
if (left < right)
{
int keyi = PartSort2(a, left, right);
//[left,keyi-1] keyi [keyi+1,right]
//PrintSort(a + left, right - left + 1);
QuickSort(a, left, keyi - 1);
QuickSort(a, keyi + 1, right);
}
}
PrintSort(int*a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\\n");
}
void TestQuickSort()
{
int a[] = { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 };//{ 5, 7, 4, 8, 6, 3, 9, 1, 2 };
int n = sizeof(a) / sizeof(int);
//QuickSort(a, 0, n - 1);
QuickSort(a, 0, n - 1);
PrintSort(a, n);
}
版本3:前后指针
void swap(int*x,int*y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int PartSort3(int*a, int left, int right)
{
int keyi = left;
int prev = left;
int cur = prev + 1;
while (cur <= right)
{
if (a[cur] < a[keyi] && prev++ != cur)//当prev与cur不相等的时候交换,相等的话就没必要交换
swap(&a[prev],&a[cur]);
cur++;
/*if (a[cur] < a[keyi])
{
prev++;
if (a[prev] > a[keyi])
{
swap(&a[prev], &a[cur]);
cur++;
}
else
{
cur++;
}
}
else
{
cur++;
}*/
}
swap(&a[prev],&a[keyi]);
return prev;
}
PrintSort(int*a,int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ",a[i]);
}
}
int main()
{
int a[] = { 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 };
int n = sizeof(a) / sizeof(int);
int left = 0;
int right = n - 1;
int ret = PartSort3(a,0,n-1);
printf("%d\\n",ret);
PrintSort(a,n);
return 0;
}
快排非递归:
void QuickSortNonR(int* a, int left, int right)
{
ST st;
StackInit(&st);
StackPush(&st,right);
StackPush(&st, left);
while (!StackEmpty(&st))
{
int begin = StackTop(&st);
StackPop(&st);
int end = StackTop(&st);
StackPop(&st);
int keyi = PartSort3(a,begin,end);
//[begin,keyi-1] keyi [keyi+1,end]
if (keyi + 1 < end)
{
StackPush(&st, end);
StackPush(&st, keyi+1);
}
if (keyi - 1 > begin)
{
StackPush(&st, keyi-1);
StackPush(&st, begin);
}
}
StackDestroy(&st);
}
以上是关于数据结构快排专题的主要内容,如果未能解决你的问题,请参考以下文章