工厂模式——排序方法的封装
来源:互联网 发布: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、归并排序:
- 工厂模式——排序方法的封装
- 简单工厂模式——把生产方法封装起来
- 使用工厂方法模式和策略模式封装常用排序算法
- 设计模式——抽象工厂模式、工厂方法模式
- Java设计模式—工厂方法模式&抽象工厂模式
- Java设计模式—工厂方法模式&抽象工厂模式
- 设计模式—工厂方法
- 设计模式—工厂方法
- 体系结构—工厂方法模式
- 设计模式——简单工厂,工厂方法,抽象工厂
- 设计模式——简单工厂、工厂方法、抽象工厂
- 三兄弟模式 —简单工厂&工厂方法&抽象工厂
- 模式四:工厂模式(Factory Pattern)——封装对象的创建
- 工厂三姐妹对比总结——简单工厂模式&工厂方法模式&抽象工厂模式
- c++实现工厂方法模式对八大排序的统一管理
- Head First 设计模式学习——简单工厂方法-工厂方法模式-抽象工厂模式
- 设计模式——工厂方法模式
- 设计模式——工厂方法模式
- 输入输出流
- CSS3:媒体查询
- Get方式中文乱码问题
- 大数据数据来源
- 160家优秀国外技术公司博客
- 工厂模式——排序方法的封装
- bzoj3926(广义后缀自动机)
- 不怕得罪人地推荐这9本黑客书籍
- 常见正则
- 5、Javascript的函数名加括号和不加括号的区别
- R语言学习四 图像的绘制一
- 大数据应用
- 简单有道词典客户端C实现
- 关于委托的一个简单小练习