采用基于“五元中值组取中值分割法”的线性 时间选择算法,找出 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- 1])

              {

                     l[j]= l[j - 1];

                     j--;

              }

              l[i]= temp;

       }

}

 

voidSortableList::Input()

{

       cout<<"请输入元素"<< endl;

       for (int i = 0;i<maxSize; i++)

       {

              cin>> l[i];

              n++;

       }

       l[n]= INF;

}

 

voidSortableList::Output()

{

       cout<<"序列元素为:"<< endl;

       for (int i = 0;i<maxSize; 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]<l[left]);

              do j--; while (l[j]>l[left]);

              if (i<j) Swap(i,j);

       }while (i<j);

       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<j - left + 1)  //在左子表求第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;

}

你可能感兴趣的:(C++算法设计)