工厂模式——排序方法的封装

来源:互联网 发布:php手册中文版 编辑:程序博客网 时间:2024/06/10 10:55


作业题:

实现一个排序系统

           相关知识:

1、接口(C++叫抽象类)

2、排序算法:冒泡排序、快速排序、直接插入排序、归并排序

3、工厂模式

要求:

A、定义一个排序抽象类(即接口),所有的排序函数继承实现这个抽象类

B、将排序函数封装成一个工厂类

输入:

         10

         10 9 8 76 5 4 3 2 1

注:第一个数是数组元素个数,第二个是数组中元素

输出:

        1 2 3 4 56 7 8 9 10

训练目标:

理解面向对象的思想

学会同类的继承和接口的使用

问题分析:

(一) 四种排序算法的原理是什么?

(二) 什么叫抽象类?如何定义它?它有什么作用?

(三) 什么叫工厂模式?它是如何实现的?

(四) 编写的过程中要注意哪些细节?<在代码中会有注释>

问题解决(一)四种排序算法的原理是什么?

        冒泡排序<BubbleSort>——从小到大

1、基本思想:两个数两个数比较大小,较大的数下沉,较小的数冒起来。

2、过程:

A、比较相邻的两个数据,如果第一个数比第二的数大就交换位置。

B、从前到后两两比较,一直比较到最后两个数据 。最终最大的数据被交换到最后的位置,这样最后一个最大数的位置就排好了。

C、继续重复上述操作,依次将第n-1,n-2…2,1个最大数排好位置。

3、图示:

4、代码实现:

void BubbleSort(int a[],int n){int i,j,temp=0; //定义变量的时候顺便初始化,Int i=0,j=0,temp =0;这里也许用处不大,但是要养成重视初始化变量的习惯for(i=0;i<n-1;i++){    int count=0;//是否交换的标志for(j=0;j<n-1-i;j++){if(a[j]>a[j+1]){temp=a[j];a[j]=a[j+1];a[j+1]=temp;count=1;}}            if(count==0)//若循环一轮结束后,没有发生交换,则说明该数据顺序已经排好,无需继续进行下去                break;}}

 快速排序<QuickSort>

1、 基本思想:快速排序采用的是分治法,通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

2、过程:

A、设置两个变量i、j,排序开始的时候:i=0,j=n-1;

  B、以第一个数组元素作为关键数据,赋值给key,即 key=a[0];

  C、从j开始向前搜索,即由后开始向前搜索(j=j-1即j--),找到第一个小于key的值a[j],a[j]与a[i]交换;

     D、从i开始向后搜索,即由前开始向后搜索(i=i+1即i++),找到第一个大于key的a[i],a[i]与a[j]交换;

  E、重复第3、4、5步,直到 i=j; (3,4步是在程序中没找到时候j=j-1,i=i+1,直至找到为止。找到并交换的时候i, j指针位置不变。另外当i=j这过程一定正好是i++或j--完成的最后交换,到此循环结束。)

3、示意图:

4、代码实现:

void QuickSort(int a[],int left,int right){    if(left<right)    {        int key=a[left];        int i=left;        int j=right;        while(i<j)        {            while(i<j&&a[j]>=key)            {                j--;            }            a[i]=a[j];            while(i<j&&a[i]<=key)            {                i++;            }            a[j]=a[i];        }        a[i]=key;        QuickSort(a,left,i-1);        QuickSort(a,i+1,right);    }}

直接插入排序<InsertionSort>

1、基本思想:在要排序的一组数中,假定前n-1个数已经排好序,现在将第n个数插到前面的有序数列中,使得这n个数也是排好顺序的。这样反复循环,直到全部排好序。

2、过程:

A、假设数组中a[0]就是排序好的第一个数,用a[1]和a[0]比较,如果a[1]<a[0]则a[0]和a[1]数值交换。

B、然后再用a[2]先和a[1]比较如果a[2]>a[1];则跳出循环,如果a[2]<a[1],a[2]和a[1]就交换,在比较a[1]和a[0],如果a[1]<a[0],那么a[1]和a[0]交换。如此循环直到数组全部有序。

3、图示:

4、代码实现:

void InsertionSort(int a[],int n){    int temp;    for(int i=0;i<n-1;i++)    {        for(int j=i+1;j>0;j--)        {            if(a[j]<a[j-1])            {                temp=a[j-1];                a[j-1]=a[j];                a[j]=temp;            }            else                break;        }    }}

归并排序<MergeSort>

1、基本思想:归并排序是建立在归并操作上的一中有效的排序算法。该算法是采用分治的思想。

2、过程:

A、首先要考虑如何将2个有序数列合并。只要比较2个数列的第一个数,谁小就先取谁,取了后就在对应数列中删除这个数。然后再进行比较,如果数列为空,那直接将另一个数列的数据依次取出即可。

B、解决了上面合并的问题,再来看归并排序,其中的基本思想就是将数组分成2组A、B,如果这2组数据都是有序的,那么就可以很方便的将这2组数据进行排序。

C、如何使这2组组内数据有序?可以将A,B组各自再分成2组。依次类推,当分出来的小组只有1个数据时,可以认为这个小组组内已经达到了有序,然后再合并相邻的2个小组就可以了。这样通过先分解数列,再合并数列就完成了归并排序。

3、图示:

4、代码实现:

//合并 :将两个序列a[first-middle],a[middle+1-last]合并void Merge(int a[],int first,int middle,int last,int temp[]){    int i = first;    int m = middle;    int j = middle+1;    int n = last;    int k = 0;    while(i<=m && j<=n)    {        if(a[i] <= a[j])        {            temp[k] = a[i];            k++;            i++;        }        else        {            temp[k] = a[j];            k++;            j++;        }    }    while(i<=m)    {            temp[k] = a[i];            k++;            i++;    }    while(j<=n)    {        temp[k] = a[j];        k++;        j++;    }    for(int i=0;i<k;i++)    {        a[first + i] = temp[i];    }}void MergeSort(int a[],int first,int last,int temp[]){    if(first < last)    {        int middle = (first + last)/2;        MergeSort(a,first,middle,temp);    //左半部分排好序        MergeSort(a,middle+1,last,temp);  //右半部分排好序        Merge(a,first,middle,last,temp);    //合并左右部分    }}

问题解决(二)什么叫抽象类?如何定义它?它有什么作用?

         抽象类:含有纯虚函数的类叫做抽象类。

         如:class SORT

                   {

                            Public:

                                     VirtualSort ( int a[] , int n ) = 0 ;//在父类中只做声明,函数体为空,必须在子类中实现

                                     Virtual~SORT ( )   

                                     {

                                               Cout<< ”Release the SORT object.”<<endl ;//验证该虚析构函数是否被调用

                                     }//定义一个虚析构函数,在运行多态时能够通过delete父类指针,释放子类对象,避免了内存的泄露

                   } ;

抽象类的作用:有利于多态性,抽象的型别统一类型,来进行操作,有利于以后的扩展,移植,复用。

问题解决(三)什么叫工厂模式?它是如何实现的?

         工厂模式:为创建对象提供过渡接口,以便将创建的对象的具体过程屏蔽隔离起来,达到提高灵活性的目的。就这道题来讲:即一个工厂是生产排序功能的,你现在需要排序一组数,你就跟工厂说给我用冒泡法排序它,然后工厂就会给你一个用冒泡法排好序的数组,如果你跟工厂说给我用快排排序它,工厂就会给你一个用快排排序好的数组。

         工厂模式示意图:

编写代码:

#include <iostream>using namespace std;#include <stdlib.h>enum SORTTYPE { Bubble =1, Quick=2, Insertion=3, Merge=4,Selection=5,Exchange=6 };void menu();                   //显示用户界面template <class T>             //因为四种排序算法中的形参类型可能不同,所以要定义函数模板class SORT                     //定义SORT抽象类 作为基类  下面的四个排序类是它的派生类 继承它的Sort(....);{public:virtual void Sort(T a[], int n) = 0;     //在父类中声明纯虚函数,子类必须实现它,否则子类不能实例化,子类继承Sort(...)时形参要和父类保持一致virtual ~SORT()                          //定义虚析构函数,通过delete父类指针释放子类对象{cout << "Release the base sort object" << endl;//检验是否释放了SORT对象}};template <class T>class BubbleSort :public SORT <T>    //定义冒泡排序类 public继承SORT类 要继承SORT类中的成员函数模板 每个派生类的声明都要加上<T>{public:void Sort(T a[], int n);     //冒泡排序,先声明,实现放在main函数的下面,这样能够加强程序的可读性~BubbleSort(){cout << "Release Bubble Sort object" << endl; //检验是否释放BubbleSort的对象}};template <class T>class QuickSort :public SORT<T>   //定义快速排序类 public继承SORT类 要继承SORT类中的成员函数模板 每个派生类的声明都要加上<T>{public:void Sort(T a[], int n);void qsort(T a[], int left, int right);  //快速排序的形参和Sort(...)不一致,所以快排算法重新声明一个函数,然后再在Sort(...)调用~QuickSort(){cout << "Rlease QuickSort object" << endl;  //检验是否释放了QuickSort的对象}};template <class T>class InsertionSort :public SORT<T> //定义插入排序类 public继承SORT类 要继承SORT类中的成员函数模板 每个派生类的声明都要加上<T>{public:void Sort(T a[], int n);    //插入排序的声明,实现放在main函数的下面,这样能够加强程序的可读性~InsertionSort(){cout << "Release Insertion Sort object " << endl; //检验是否释放了InsertionSort的对象}};template <class T>class MergeSort :public SORT<T>       //定义归并排序类 public继承SORT类 要继承SORT类中的成员函数模板 每个派生类的声明都要加上<T>{public:void Merge(T a[],int first,int middle,int last,T temp[]);void Sort(T a[], int n);        //因为归并排序的形参与Sort(...)不一致,所以重新声明msort(...)来实现归并排序,再在Sort(...)调用void msort(T a[],int first,int last,T temp[]);//归并排序,他要调用Merge函数才能完成排序~MergeSort(){cout << "Release Merge Sort Object" << endl;//检验是否释放了MergeSort的对象}};template<class T>class SelectionSort :public SORT<T>{public:    void Sort(T a[],int n);    ~SelectionSort()    {        cout<<"Release Selection Sort object"<<endl;//检验是否释放了SelectionSort的对象    }};template<class T>class ExchangeSort:public SORT<T>{    void Sort(T a[],int n);    ~ExchangeSort()    {        cout<<"Release Exchange Sort object"<<endl;    }};template<class T>class Factory              //定义一个工厂类,将四种排序算法封装在该类中,要用时通过父类指针调用子类对象{public:SORT<T> *pFather;      //定义一个父类指针对象T *datas;             //定义Factory类数据成员int size;Factory(){ pFather = NULL ; datas = NULL ; } //定义构造函数将NULL赋值给*pFather和*datasvoid Input();  //用户输入函数 具体注释在下面的定义中void Show();   //打印排序后的数组SORT<T>  *creatSort(SORTTYPE type)  //定义SORT类的返回指针类型的成员函数作为Factory的成员函数,使SORT类指针PFather能够调用之类对象{switch (type){case Bubble:return new BubbleSort<T>();    //返回子类的对象指针赋给父类指针即pFatherbreak;case Insertion:return new InsertionSort<T>(); //返回子类的对象指针赋给父类指针即pFatherbreak;case Merge:return new MergeSort<T>();     //返回子类的对象指针赋给父类指针即pFatherbreak;            case Selection:                return new SelectionSort<T>(); //返回子类的对象指针赋给父类指针即pFather                break;            case Exchange:                return new ExchangeSort<T>();  //返回子类的对象指针赋给父类指针即pFather                break;default:return new QuickSort<T>();     //输入0-6之外的数字时候默认返回快排类的指针break;}}void Run(SORTTYPE type){pFather = creatSort(type);       //creatSort函数返回子类对象的指针赋给父类指针即pFatherInput();if (pFather != NULL)             //判断子类的对象指针有没有成功赋值给*pFather{pFather->Sort(datas,size);   //通过父类的pFather指针可以调用子类的Sort(...)函数}Show();}~Factory(){if (pFather != NULL)             //释放前判空{delete pFather;pFather = NULL;              //释放对象后,立即把指针设置为NULL,防止产生“野指针”cout << "Release the Factory object" << endl;}if (datas != NULL)             //释放前判空{delete[]datas;datas = NULL;             //释放对象后,立即把指针设置为NULL,防止产生“野指针”cout << "Release the data array" << endl;//检验是否释放了Factory 的对象}}};int main(){int choose;char yes_no;do{        Factory<double> *factory = new Factory<double>(); //在堆上申请一段内存。<推荐阅读C++动态分配内存>        menu();        cout << endl << "---Please select the sort to use (enter the digital 0-6): ";//让用户选择要用的排序        cin >> choose;        if (choose < 0 || choose >6)        {            choose = 2;   //输入0-6以外的数字,默认使用快排        }        if (choose==0)            exit(0);      //输入0 退出排序系统        factory->Run((SORTTYPE)choose);        if (factory != NULL) //在堆上申请的对象必须用户自己释放 释放前判空        {            cout << endl << "--------------------------------------------" << endl;//检验是否释放了Factory 的对象            delete factory;            factory = NULL; //释放对象后,立即把指针设置为NULL,防止产生“野指针”            cout << endl << "--------------------------------------------" << endl;        }        cout<<endl<<"Do you want to continue ? [y/n]"<<endl;//一次排序结束后,询问用户是否要继续使用该排序系统   do{ cin>>yes_no; break;                }while(yes_no!='Y'&&yes_no!='y'&&yes_no!='N'&&yes_no!='n');//当用户输入非法字符时让用户循环输入直至合法为止  if(yes_no=='N'||yes_no=='n')//用户输入0退出系统 {  exit(0);  break; }        }while(yes_no!='Y'||yes_no!='y');return 0;}template <class T>void BubbleSort<T>::Sort(T a[], int n)//冒泡排序定义 {T temp;for(int i=0;i<n-1;i++){    int count=0;    //是否交换的标志for(int j=0;j<n-1-i;j++){if(a[j]>a[j+1]){temp=a[j];a[j]=a[j+1];a[j+1]=temp;count=1;}}            if(count==0)  //若循环一轮结束后,没有发生交换,则说明该数据顺序已经排好,无需继续进行下去                break;}}template <class T>void QuickSort<T>::Sort(T a[], int n){qsort(a, 0, n - 1);}template <class T>void QuickSort<T>::qsort(T a[], int left, int right)//快速排序定义{if (left < right){T key = a[left];int i = left;int j = right;while (i < j){while (i < j&&a[j] >= key){j--;}a[i] = a[j];while (i < j&&a[i] <= key){i++;}a[j] = a[i];}a[i] = key;qsort(a, left, i - 1);  //调用自身qsort(a, i + 1, right);//调用自身}}template <class T>void InsertionSort<T>::Sort(T a[], int n) //插入排序{int temp;    for(int i=0;i<n-1;i++)    {        for(int j=i+1;j>0;j--)        {            if(a[j]<a[j-1])            {                temp=a[j-1];                a[j-1]=a[j];                a[j]=temp;            }            else                break;        }    }}template <class T>void MergeSort<T>::Merge(T a[],int first,int middle,int last,T temp[]){int i = first;    int m = middle;    int j = middle+1;    int n = last;    int k = 0;    while(i<=m && j<=n)    {        if(a[i] <= a[j])        {            temp[k] = a[i];            k++;            i++;        }        else        {            temp[k] = a[j];            k++;            j++;        }    }    while(i<=m)    {            temp[k] = a[i];            k++;            i++;    }    while(j<=n)    {        temp[k] = a[j];        k++;        j++;    }    for(int i=0;i<k;i++)    {        a[first + i] = temp[i];    }}template <class T>void MergeSort<T>::msort(T a[],int first,int last,T temp[])//归并排序{if(first < last)    {        int middle = (first + last)/2;        msort(a,first,middle,temp);//左半部分排好序        msort(a,middle+1,last,temp);//右半部分排好序        Merge(a,first,middle,last,temp); //合并左右部分    }}template <class T>void MergeSort<T>::Sort(T a[], int n){    T temp[n];msort(a,0,n-1,temp);}template <class T>void SelectionSort<T>::Sort(T a[],int n)  //选择排序{    T temp;    int k;    for(int i=0;i<n-1;i++)    {        k=i;        for(int j=i+1;j<n;j++)        {            if(a[j]<a[k])                k=j;        }        if(k!=i)        {            temp=a[k];            a[k]=a[i];            a[i]=temp;        }    }}template <class T>void ExchangeSort<T>::Sort(T a[],int n) //交换排序{    T temp;    for(int i=0;i<n-1;i++)    {        for(int j=i+1;j<n;j++)        {            if(a[j]<a[i])            {                temp=a[i];                a[i]=a[j];                a[j]=temp;            }        }    }}void menu(){cout <<endl<<"***********************************************************************" << endl;cout << "      -----ORDERING  SYSTEM-----" << endl << endl;cout << "--------NO.1  Bubble     sort(1)-------- " << endl;cout << "--------NO.2  Quick      sort(2)-------- " << endl;cout << "--------NO.3  Insertion  sort(3)-------- " << endl;cout << "--------NO.4  Merge      sort(4)-------- " << endl;cout << "--------NO.5  Selection  sort(5)-------- " << endl;cout << "--------NO.6  Exchange   sort(6)-------- " << endl;cout << "--------Zero  Exit the system(0)-------- " <<endl;cout <<endl<<"***********************************************************************" << endl;}template <class T>void Factory<T>:: Input(){size = 0;cout << "Input Datas Size: " ;//提示用户输入数组长度cin >> size;cout << "Input the datas: ";//提示用户输入待排序数组if (datas != NULL){delete[]datas;  //在堆上申请的对象必须用户自己释放 释放前判空datas = NULL;  //释放对象后,立即把指针设置为NULL,防止产生“野指针”        }datas = new T[size];//在堆上申请内存     <推荐阅读C++动态分配内存>if (datas == NULL)//判断内存分配是否成功{cout << "Get Memoery Failed, exit" << endl;exit(0);}int i = 0;while (i < size){cin >> datas[i++];//相当于 cin>>datas[i];i++;}}template <class T>void Factory<T>::Show(){cout << "The result is as below:" << endl;for (int j = 0; j < size; j++)cout << datas[j] << " ";}



功能实现:

1、冒泡排序:



2、快速排序:



3、直接插入排序:



4、归并排序:




1 0
原创粉丝点击