赞
踩
三数取中是一种优化快速排序算法的方法,可以提高排序的效率。传统的快速排序算法是以待排序数组的第一个元素为基准进行划分,但是如果待排序数组已经有序或接近有序,会导致快速排序的效率很低。三数取中的优化方法是选取待排序数组的头、尾和中间位置的三个元素,然后将这三个元素按照从小到大的顺序排列,取中间的元素作为基准。
- int GetMidIndex(int* a, int left, int right)
- {
- int mid = (left + (rand() % (right - left))) / 2;
- if (a[left] < a[mid])
- {
- if (a[mid] < a[right])
- {
- return mid;
- }
- else if (a[left] < a[right])
- {
- return right;
- }
- else
- {
- return left;
- }
-
- }
- else
- {
- if (a[left] < a[right])
- {
- return left;
- }
- else if (a[mid] > a[right])
- {
- return mid;
- }
- else
- {
- return right;
- }
-
- }
- return left;
- }
三路划分是对快速排序的一种优化方法,能够处理含有大量重复元素的数组。传统的快速排序将数组划分为两个部分,使得左半部分的元素都小于等于选定的主元素,右半部分的元素都大于等于主元素。
而三路划分将数组划分为三个部分,分别是小于、等于和大于主元素的部分。具体实现方法如下:
1. 随机选择一个元素作为主元素。
2. 用两个指针分别指向数组的开头和结尾,并且用第三个指针记录当前位置。
3. 从头开始遍历数组,若当前元素小于主元素,则将该元素与小于部分的下一个位置进行交换,并将小于部分的指针往后移动,当前位置也向后移动。
4. 若当前元素等于主元素,则将当前位置向后移动。
5. 若当前元素大于主元素,则将该元素与大于部分的前一个位置进行交换,并将大于部分的指针往前移动,但当前位置不变。
6. 重复上述步骤,直到当前位置指针与大于部分的指针相遇。
通过三路划分,能够将数组划分为小于、等于和大于主元素的三个部分,然后递归地对小于和大于部分进行排序。这样可以避免重复元素的多次比较,从而提高快速排序的效率。
- void QuickSort(int* a, int begin, int end)
- {
- if (begin >= end)
- {
- return;
- }
- //优化 三路划分 将等于key的收录到中间;
- int left = begin;
- int right = end;
- int cur = left + 1;
-
- srand(time(0));
-
-
- int midi = GetMidIndex(a, left, right);
- Swap(&a[left], &a[midi]);
- int key = a[left];
-
- while (cur <= right)
- {
- if (a[cur] < key )
- {
- Swap(&a[cur++], &a[left++]);
- }
- else if (a[cur] > key)
- {
- Swap(&a[cur], &a[right--]);
- }
- else if (a[cur] == key)
- {
- cur++;
- }
-
- }
-
-
- QuickSort(a, begin, left - 1);
- QuickSort(a, right + 1, end);
- }
- int ParkSort(int* a, int left, int right)
- {
- int midi = GetMidIndex(a, left, right);//三数取中
- Swap(&a[left], &a[midi]);
- int keyi = left;
- while (left < right)
- {
-
- while (left < right && a[right] >= a[keyi])
- {
- --right;
- }
-
- while (left < right && a[left] <= a[keyi])
- {
- ++left;
- }
- Swap(&a[right], &a[left]);
- }
-
- Swap(&a[keyi], &a[left]);
- return left;
- }
- //快速排序--- 挖坑法
- int ParkSort2(int* a, int left, int right)
- {
- int midi = GetMidIndex(a, left, right);
- Swap(&a[left], &a[midi]);
- int key = a[left];
- int hole = left;
- while (left < right)
- {
-
- while (left < right && a[right] >= a[key])
- {
- --right;
- }
- a[hole] = a[right];
- hole = right;
- while (left < right && a[left] <= a[key])
- {
- ++left;
- }
- a[hole] = a[left];
- hole = left;
- }
-
- a[hole] = key;
- return hole;
- }
- int PartSort3(int* a, int left, int right)
- {
- int midi = GetMidIndex(a, left, right);
- Swap(&a[left], &a[midi]);
-
-
- int keyi = left;
- int prev = left;
- int cur = left+1;
- while (cur <= right)
- {
- if (a[cur] < a[keyi] && ++prev != cur)
- {
- Swap(&a[cur], &a[prev]);
- }
- cur++;
- }
- Swap(&a[prev], &a[keyi]);
- keyi = prev;
- return keyi;
- }
- void QuickSortNonR(int* a, int begin, int end)
- {
- Stack st;
- StackInit(&st);
- StackPush(&st, end);
- StackPush(&st, begin);
- while (!StackEmpty(&st))
- {
- int left = StackTop(&st);
- StackPop(&st);
-
- int right = StackTop(&st);
- StackPop(&st);
-
- int keyi = PartSort3(a, left, right);
-
- if (keyi + 1 < right)
- {
- StackPush(&st, right);
- StackPush(&st, keyi+1);
- }
- if (keyi - 1 > left)
- {
- StackPush(&st, keyi - 1);
- StackPush(&st, left);
- }
- }
- StackDestroy(&st);
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。