本次作业分三道题,但是基本都是差不多的,就是quicksort,题目要求如下:
Download the text file here.
The file contains all of the integers between 1 and 10,000 (inclusive, with no repeats) in unsorted order. The integer in the ith row of the file gives you the ith entry of an input array.
Your task is to compute the total number of comparisons used to sort the given input file by QuickSort. As you know, the number of comparisons depends on which elements are chosen as pivots, so we'll ask you to explore three different pivoting rules.
You should not count comparisons one-by-one. Rather, when there is a recursive call on a subarray of length m, you should simply add m−1 to your running total of comparisons. (This is because the pivot element is compared to each of the other m−1 elements in the subarray in this recursive call.)
WARNING: The Partition subroutine can be implemented in several different ways, and different implementations can give you differing numbers of comparisons. For this problem, you should implement the Partition subroutine exactly as it is described in the video lectures (otherwise you might get the wrong answer).
DIRECTIONS FOR THIS PROBLEM:
For the first part of the programming assignment, you should always use the first element of the array as the pivot element.
HOW TO GIVE US YOUR ANSWER:
Type the numeric answer in the space provided.
So if your answer is 1198233847, then just type 1198233847 in the space provided without any space / commas / other punctuation marks. You have 5 attempts to get the correct answer.
(We do not require you to submit your code, so feel free to use the programming language of your choice, just type the numeric answer in the following space.)
See the first question.
DIRECTIONS FOR THIS PROBLEM:
Compute the number of comparisons (as in Problem 1), always using the final element of the given array as the pivot element. Again, be sure to implement the Partition subroutine exactly as it is described in the video lectures. Recall from the lectures that, just before the main Partition subroutine, you should exchange the pivot element (i.e., the last element) with the first element.
See the first question.
DIRECTIONS FOR THIS PROBLEM:
Compute the number of comparisons (as in Problem 1), using the "median-of-three" pivot rule. [The primary motivation behind this rule is to do a little bit of extra work to get much better performance on input arrays that are nearly sorted or reverse sorted.] In more detail, you should choose the pivot as follows. Consider the first, middle, and final elements of the given array. (If the array has odd length it should be clear what the "middle" element is; for an array with even length 2k, use the kth element as the "middle" element. So for the array 4 5 6 7, the "middle" element is the second one ---- 5 and not 6!) Identify which of these three elements is the median (i.e., the one whose value is in between the other two), and use this as your pivot. As discussed in the first and second parts of this programming assignment, be sure to implement Partition exactly as described in the video lectures (including exchanging the pivot element with the first element just before the main Partition subroutine).
第一种是将第一个元素作为pivot
第二种是将最后一个元素作为pivot
第三种是为了防止该序列是近似正序或者反序的,所以选择第一个,最后一个和中间的元素的中值作为pivot
先讲讲quicksort的实现吧,
下面是我第一题的代码:
# include
# include
# include
using namespace std;
/* prototype of the two functions in quicksort */
long sort(vector&, int, int);
int partition(vector&, int, int);
int main(int argc, char** argv) {
vector num;
/* store the elements in txt file into num vector */
ifstream infile;
infile.open("QuickSort.txt", ios::in);
int tmp;
while (infile >> tmp)
num.push_back(tmp);
infile.close();
/* start sorting */
long cnt = 0;
cnt = sort(num, 0, num.size()-1);
for (int i = 0; i < num.size(); ++i)
cout << num[i] << endl;
cout << cnt << endl;
return 0;
}
long sort(vector& num, int low, int high) {
if (high <= low)
return 0;
int pivot = partition(num, low, high);
int tmp1 = sort(num, low, pivot-1);
int tmp2 = sort(num, pivot+1, high);
return (tmp1 + tmp2 + (high - low));
}
int partition(vector& num, int low, int high) {
int pivot = num[low];
int i = low + 1;
int j;
for (j = low + 1; j <= high; ++j) {
if (num[j] < pivot) {
swap(num[j], num[i]);
++i;
}
/* else, do nothing */
}
swap(num[low], num[i-1]);
return (i - 1);
}
下面的sort和partition构成了quicksort
基本步骤是先partition,partition返回的值是pivot,即可以固定位置的值,之后,这个位置就固定了。。此时再对low~pivot-1和pivot+1~high分别sort。持续sort下去。。这个算法跟上次作业mergesort一样是一种divide & conquer算法。
再讲讲partition的过程,这个跟我原来看普林斯顿那本红皮书实现partition的方式有些区别。。
上张图来说明如何实现选择第一个元素作为pivot实现partition的过程:
基本原则就是j用来遍历,而i是作为大于3和小于3的分界线。。
然后最后num[low]和num[i-1]互换位置i-1就是pivot,其所处位置也是完全sorted之后应该位于的位置。。
再上传下第二题,和第三题代码,第二题基本和第一题一样,第三题也差不了太远,只不过加了个函数用来选择三个元素的中值而已:
# include
# include
# include
using namespace std;
/* prototype of two functions in quicksort */
long sort(vector&, int, int);
int partition(vector&, int, int);
int main(int argc, char** argv) {
vector num;
/* store the elements in txt file into num vector */
ifstream infile;
infile.open("1000.txt", ios::in);
int tmp;
while (infile >> tmp)
num.push_back(tmp);
infile.close();
/* start sorting */
long cnt;
cnt = sort(num, 0, num.size()-1);
for (int i = 0; i < num.size(); ++i)
cout << num[i] << endl;
cout << "# of comparisons: " << cnt << endl;
return 0;
}
long sort(vector& num, int low, int high) {
if (high <= low)
return 0;
int pivot = partition(num, low, high);
int tmp1 = sort(num, low, pivot-1);
int tmp2 = sort(num, pivot+1, high);
return (tmp1 + tmp2 + (high - low));
}
int partition(vector& num, int low, int high) {
int pivot = num[high];
swap(num[low], num[high]);
int i = low + 1;
int j;
for (j = low + 1; j <= high; ++j) {
if (num[j] < pivot) {
swap(num[i], num[j]);
++i;
}
/* else, do nothing */
}
swap (num[i-1], num[low]);
return (i-1);
}
# include
# include
# include
using namespace std;
long sort(vector&, int, int);
int partition(vector&, int, int);
int median_of_3(vector&, int, int, int);
int main(int argc, char** argv) {
vector num;
/* store the elements in txt file into num vector */
ifstream infile;
infile.open("QuickSort.txt", ios::in);
int tmp;
while (infile >> tmp)
num.push_back(tmp);
infile.close();
/* start sorting */
long cnt = sort(num, 0, num.size()-1);
for (int i = 0; i < num.size(); ++i)
cout << num[i] << endl;
cout << "# of comparisons: " << cnt << endl;
return 0;
}
long sort(vector& num, int low, int high) {
if (high <= low)
return 0;
int pivot = partition(num, low, high);
long tmp1 = sort(num, low, pivot-1);
long tmp2 = sort(num, pivot+1, high);
return (tmp1+tmp2+(high-low));
}
int partition(vector& num, int low, int high) {
int index = median_of_3(num, low, high, (low+high)/2);
int pivot = num[index];
swap(num[low], num[index]);
int i = low + 1;
int j;
for (j = low + 1; j <= high; ++j) {
if (num[j] < pivot) {
swap(num[i], num[j]);
++i;
}
/* else do nothing */
}
swap(num[i-1], num[low]);
return (i-1);
}
int median_of_3(vector& num, int low, int high, int medium) {
if (num[low] > max(num[medium], num[high])) {
if (num[medium] > num[high])
return medium;
else
return high;
}
else if (num[low] < min(num[medium], num[high])) {
if (num[medium] > num[high])
return high;
else
return medium;
}
else
return low;
}