问题描述
我正在从事一个项目,该项目要求我们实现不同的排序并添加计数器变量以测量具有不同数组大小的运行时。
我已经完成了插入排序并正确计算了比较次数。
我可以使用引用参数。
感谢任何反馈。
输出:[从答案更新]
Quick sort 16 384 6401 74378
预期输出:
Array Size: 10 100 1000 10000
--------------------------------------------------------------------
Quick Sort 35 630 10292 132882
数组大小为 10 的数组内容是什么:
内容与使用的种子保持一致。
Insertion sort
[ 935,942,697,299,382,579,408,181,366,505 ] //unsorted
[ 181,505,935,942 ] //sorted
程序:[从答案更新]
#include <iostream>
#include <stdlib.h>
#include <iomanip>
#include <cmath>
/******************************/
/* Start of Quick Sort Algorithm */
/******************************/
static const int MIN_SIZE = 10; // Smallest size of an array that quicksort will sort
/**
* Sorts the items in an array into ascending order.
*/
template<class ItemType>
int insertionSort(ItemType theArray[],int first,int last) {
int count = 0;
for (int unsorted = first + 1; unsorted <= last; unsorted++) {
ItemType nextItem = theArray[unsorted];
int loc = unsorted;
while ((loc > first) && (count++,theArray[loc - 1] > nextItem)) {
theArray[loc] = theArray[loc - 1];
loc--;
}
theArray[loc] = nextItem;
}
return count;
}
/**
* Arranges two specified array entries into sorted order by
* exchanging them,if necessary.
* */
template<class ItemType>
void order(ItemType theArray[],int i,int j) {
if (theArray[i] > theArray[j]) {
std::swap(theArray[i],theArray[j]);
}
}
/**
* Arranges the first,middle,and last entry in an array in sorted order.
*/
template<class ItemType>
int sortFirstMiddleLast(ItemType theArray[],int last) {
int mid = first + (last - first) / 2;
order(theArray,first,mid); // Make theArray[first] <= theArray[mid]
order(theArray,mid,last); // Make theArray[mid] <= theArray[last]
order(theArray,mid); // Make theArray[first] <= theArray[mid]
return mid;
}
/**
* Partitions the entries in an array about a pivot entry for quicksort.
*/
template<class ItemType>
int partition(ItemType theArray[],int last,int &counter) {
// Choose pivot using median-of-three selection
int pivotIndex = sortFirstMiddleLast(theArray,last);
// Reposition pivot so it is last in the array
std::swap(theArray[pivotIndex],theArray[last - 1]);
pivotIndex = last - 1;
ItemType pivot = theArray[pivotIndex];
// Determine the regions S1 and S2
int indexFromLeft = first + 1;
int indexFromright = last - 2;
bool done = false;
while (!done) {
// Locate first entry on left that is >= pivot
while (theArray[indexFromLeft] < pivot) {
counter++;//I incremented Count here
indexFromLeft = indexFromLeft + 1;
}
// Locate first entry on right that is <= pivot
while (theArray[indexFromright] > pivot) {
counter++;
indexFromright = indexFromright - 1;
}
if (indexFromLeft < indexFromright) {
std::swap(theArray[indexFromLeft],theArray[indexFromright]);
indexFromLeft = indexFromLeft + 1;
indexFromright = indexFromright - 1;
}
else {
done = true;
}
}
// Place pivot in proper position between S1 and S2,and mark its new location
std::swap(theArray[pivotIndex],theArray[indexFromLeft]);
pivotIndex = indexFromLeft;
return pivotIndex;
}
/**
* Sorts an array into ascending order. Uses the quick sort with
* median-of-three pivot selection for arrays of at least MIN_SIZE
* entries,and uses the insertion sort for other arrays.
*/
template<class ItemType>
int quicksort(ItemType theArray[],int last) {
int result = 0;
int counter = 0;
if (last - first + 1 < MIN_SIZE) {
result = insertionSort(theArray,last);
}
else {
// Create the partition: S1 | Pivot | S2
int pivotIndex = partition(theArray,last,counter);
// Sort subarrays S1 and S2
result += quicksort(theArray,pivotIndex - 1);
result += quicksort(theArray,pivotIndex + 1,last);
result += counter;
}
return result; //return final count
}
/******************************/
/* Start of Sorting Benchmark */
/******************************/
int* makeRandomArray(int n,int seed) {
srand(seed);
int * a = new int[n];
for (int i = 0; i < n; i++) {
a[i] = rand() % 1000;
}
return a;
}
int main(){
const int seed = 9000;
int *a;
/******************************/
/* Start of Quick Sort */
/******************************/
std::cout << "Quick sort";
int n = 10;
a = makeRandomArray(10,seed);
std::cout <<std::setw(13)<< quicksort(a,n-1);
delete[] a;
n = 100;
a = makeRandomArray(100,n-1);
delete[] a;
n = 1000;
a = makeRandomArray(1000,n-1);
delete[] a;
n = 10000;
a = makeRandomArray(10000,n-1)<<std::endl;
delete[] a;
return 0;
}
解决方法
在快速排序中,当分区方法/函数正在寻找违反规则的元素时进行比较,即小于主元的元素必须在主元的左侧,大于它的元素必须在右侧。这两个 while 正是这样做的。第一个继续向右移动,而当前元素小于枢轴(第一组比较)。第二个 while 做相反的操作,即,当当前元素大于主元时,它继续向左移动,进行第二组比较。如果左侧索引小于右侧索引,则表示它找到了一个大于左侧枢轴的元素和一个小于右侧枢轴的元素,因此它将交换它们。这个过程继续,直到左边的索引通过右边的索引。当它完成时,所有左边的值都小于枢轴,所有的右边值都大于枢轴,因此它将枢轴与较小侧的最后一个元素交换并返回枢轴位置,因为现在,枢轴在找到了该分区的正确位置和“中间”,允许排序过程继续到左侧分区和右侧分区。
while (theArray[indexFromLeft] < pivot) {
// count here
indexFromLeft = indexFromLeft + 1;
}
while (theArray[indexFromRight] > pivot) {
// and here
indexFromRight = indexFromRight - 1;
}