#include<iostream>
#include<ctime>
using namespace std;
void InsertSort(int* arr, int begin, int end)
{
for (int i = begin; i <= end; i++)
{
int j = begin;
while (arr[i] > arr[j])
{
j++;
}
int temp = arr[i];
for (int k = i; k >= j; k--)
{
arr[k] = arr[k - 1];
}
arr[j] = temp;
}
}
void Swap(int& a, int& b)
{
int temp = a;
a = b;
b = temp;
}
void QuickSortCore(int* arr, int begin, int end)
{
if (begin>=end)
{
return;
}
int pivot = arr[begin];
Swap(arr[begin], arr[end]);
int left = begin - 1;
int right = end;
while (left < right)
{
do
{
left++;
} while (arr[left] < pivot);
do
{
right--;
} while (arr[right] > pivot);
if (left < right)
{
Swap(arr[left], arr[right]);
}
}
Swap(arr[left], arr[end]);
QuickSortCore(arr, begin, left - 1);
QuickSortCore(arr, left + 1, end);
}
void QuickSort(int* arr, int len)
{
if (arr == nullptr || len <= 0)
{
return;
}
QuickSortCore(arr, 0, len - 1);
}
static const int len = 100000;
int main()
{
int arr[len];
for (int i = 0; i < len; i++)
{
arr[i] = rand() % len;
}
clock_t start = clock();
QuickSort(arr, len);
clock_t end = clock();
cout << "sort " << len << " num with original quicksort cost " << (double)(end - start) / CLOCKS_PER_SEC << "seconds"<<endl;
/*for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}*/
return 0;
}
改进1:待排序数目小于某个值时改用插入排序,这里取10
void InsertSort(int* arr, int begin, int end)
{
for (int i = begin; i <= end; i++)
{
int j = begin;
while (arr[i] > arr[j])
{
j++;
}
int temp = arr[i];
for (int k = i; k >= j; k--)
{
arr[k] = arr[k - 1];
}
arr[j] = temp;
}
}
原快速排序改成
void QuickSortCore(int* arr, int begin, int end)
{
if (end-begin<10)
{
InsertSort(arr, begin, end);
return;
}
int pivot = arr[begin];
Swap(arr[begin], arr[end]);
int left = begin - 1;
int right = end;
while (left < right)
{
do
{
left++;
} while (arr[left] < pivot);
do
{
right--;
} while (arr[right] > pivot);
if (left < right)
{
Swap(arr[left], arr[right]);
}
}
Swap(arr[left], arr[end]);
QuickSortCore(arr, begin, left - 1);
QuickSortCore(arr, left + 1, end);
}
运行时间如下
可以看到,运行时间比原快速排序少了一点
改进2:原支点值我们选的是待排序段的第一个值,当这个值选得不好的时候,排序效果很差,这里我们采用三值取中原则选取支点。
int MedianOfThree(int* arr, int begin, int end)
{
int index;
int median = (begin + end) / 2;
int sum = arr[begin] + arr[median] + arr[end];
int max=0x80000000, min=0x7fffffff;
if (arr[begin] > arr[median])
{
max = arr[begin];
min = arr[median];
}
if (max < arr[end])
{
max = arr[end];
}
if (min > arr[end])
{
min = arr[end];
}
int med = sum - max - min;
if (med == arr[begin])
{
index = begin;
}
else if (med == arr[median])
{
index = median;
}
else
{
index = end;
}
return index;
}
原排序代码改成
void QuickSortCore(int* arr, int begin, int end)
{
if (end-begin<10)
{
InsertSort(arr, begin, end);
return;
}
int pivot_index = MedianOfThree(arr,begin,end);
int pivot = arr[pivot_index];
Swap(arr[pivot_index], arr[end]);
int left = begin - 1;
int right = end;
while (left < right)
{
do
{
left++;
} while (arr[left] < pivot);
do
{
right--;
} while (arr[right] > pivot);
if (left < right)
{
Swap(arr[left], arr[right]);
}
}
Swap(arr[left], arr[end]);
QuickSortCore(arr, begin, left - 1);
QuickSortCore(arr, left + 1, end);
}
运行时间
运行时间并没有显著的变化,又不能取更大的运算规模,因为会栈溢出