一、实验目的和要求
理解分治法的算法思想,阅读实现书上已有的部分程序代码并完善程序,加深对分治法的算法原理及实现过程的理解。
二、实验环境(实验设备)
Code::Blocks13.12
三、实验原理及内容
一、用分治法实现一组无序序列的两路合并排序和快速排序。要求清楚合并排序及快速排 序的基本原理,编程实现分别用这两种方法将输入的一组无序序列排序为有序序列后输出。
二、采用基于“五元中值组取中值分割法”(median-of-median-of-five partitioning)的线性 时间选择算法,找出N 个元素集合 S 中的第 k 个最小的元素,使其在线性时间内解决。
源程序:
#include
#include
#include
#include
usingnamespace std;
constint INF = 2147483647;
classSortableList
{
public:
SortableList(intmSize)
{
maxSize= mSize;
l= newint[maxSize + 1];
n= 0;
}
~SortableList()
{
delete[]l;
}
void Input();
void Output();
void MergeSort();
void QuickSort();
void Select(intk) {
int j = 0;
j= Select(k, 0, n -1, 5);
cout<<"第k小元素是:"<< l[k];
}
private:
int *l;
int n; //数组中已有元素个数
int maxSize;
void MergeSort(intleft, intright);
void Merge(intleft, intmid, intright);
void InsertSort(intleft, intright);
void Swap(inti, intj); //交换下标为 i和 j的数组元素
void QuickSort(intleft, intright);
int Partition(intleft, intright);// 分化操作
int RPartition(intleft, intright);
int Select(intk, intleft, intright, intr);
};
voidSortableList::InsertSort(intleft, intright)
{
for (int i = left + 1; i <= right; i++)
{
int j = i;
int temp = l[i];
while (j>left&&temp
{
l[j]= l[j - 1];
j--;
}
l[i]= temp;
}
}
voidSortableList::Input()
{
cout<<"请输入元素"<< endl;
for (int i = 0;i
{
cin>> l[i];
n++;
}
l[n]= INF;
}
voidSortableList::Output()
{
cout<<"序列元素为:"<< endl;
for (int i = 0;i
{
cout<< l[i] <<" ";
}
cout<< endl;
}
voidSortableList::Swap(inti, intj)
{
int c = l[i];
l[i] = l[j];
l[j] = c;
}
//两路合并排序
voidSortableList::MergeSort()
{
MergeSort(0,n - 1);
}
voidSortableList::MergeSort(intleft, intright)
{
if (left<right)
{
int mid = (left + right) / 2;
MergeSort(left, mid);
MergeSort(mid+ 1, right);
Merge(left, mid, right);
}
}
voidSortableList::Merge(intleft, intmid, intright)
{
int *temp = newint[right - left + 1];
int i = left, j = mid + 1, k = 0;
while ((i <= mid) && (j<= right))
if (l[i] <=l[j])
temp[k++]= l[i++];
else
temp[k++]= l[j++];
while (i <= mid)
temp[k++]= l[i++];
while (j <= right)
temp[k++]= l[j++];
for (i = 0, k = left; k <= right;)
l[k++]= temp[i++];
}
//快速排序
intSortableList::RPartition(intleft, intright)
{
srand((unsigned)time(NULL));
int i = rand() % (right - left) + left;
Swap(i,left);
return Partition(left, right);
}
intSortableList::Partition(intleft, intright)
{
int i = left, j = right + 1;
do {
do i++; while (l[i]
do j--; while (l[j]>l[left]);
if (i
}while (i
Swap(left, j);
return j;
}
voidSortableList::QuickSort(intleft, intright)
{
if (left <= right)
{
int j = Partition(left, right);
QuickSort(left, j - 1);
QuickSort(j+ 1, right);
}
}
voidSortableList::QuickSort()
{
QuickSort(0,n - 1);
}
intSortableList::Select(intk, intleft, intright, intr)
{ //每个分组r个元素,寻找第k小元素
int n = right - left + 1;
if (n <= r)
{
InsertSort(left, right);
returnleft + k - 1; //返回第k小元素的下标
}
for (int i = 1; i <= n/ r; i++)
{
InsertSort(left + (i - 1)*r, left = i*r - 1); //二次取中规则求每组的中间值
Swap(left + i - 1, left + (i - 1)*r + (int)ceil((double)r / 2) - 1); //将每组的中间值交换到子表前部集中存放
}
int j = Select((int)ceil((double)n / r / 2), left, left + n / r - 1, r); //求二次中间值,其下标为j
Swap(left, j); //二次中间值为枢纽元,并换至left处
j= Partition(left, right); //对表(子表)进行分划操作
if (k = j - left + 1) //返回第k小元素下标
return j;
elseif (k
return Select(k, left, j - 1, r);
else
return Select(k - (j - left + 1), j + 1, right, r); //在右子表求第k-(j-left+1)小元素
}
int main()
{
SortableList sort(10);
int k = 0;
int m = 0;
sort.Input();
sort.Output();
sort.MergeSort();
sort.Output();
sort.QuickSort();
sort.Output();
cout<<"请输入你要查找的第k小元素:"<< endl;
cin>> k;
sort.Select(k);
return 0;
}