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


作业题:

实现一个排序系统

           相关知识:

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和*datas
	void Input();  //用户输入函数 具体注释在下面的定义中
	void Show();   //打印排序后的数组

	SORT<T>  *creatSort(SORTTYPE type)  //定义SORT类的返回指针类型的成员函数作为Factory的成员函数,使SORT类指针PFather能够调用之类对象
	{
		switch (type)
		{
			case Bubble:
				return new BubbleSort<T>();    //返回子类的对象指针赋给父类指针即pFather
				break;
			case Insertion:
				return new InsertionSort<T>(); //返回子类的对象指针赋给父类指针即pFather
				break;
			case Merge:
				return new MergeSort<T>();     //返回子类的对象指针赋给父类指针即pFather
				break;
            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函数返回子类对象的指针赋给父类指针即pFather
		Input();
		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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值