440 likes | 545 Views
Unit 8— 第 六 章 模板. 6.1 模板与数据结构. 6.4 模板与类参数. 6.5 函数指针与指针识别(选读). 6.2 类模板与排序查找. 6.3 索引查找与指针数组. 例 6.3 顺序表类模板设计. template < typename T, int size> class seqlist { T slist [size]; // 存放顺序表的数 组 int Maxsize ; // 最大可容纳项数 int last; // 已存表项的最后位置 public :
E N D
Unit 8—第六章 模板 6.1 模板与数据结构 6.4 模板与类参数 6.5 函数指针与指针识别(选读) 6.2 类模板与排序查找 6.3 索引查找与指针数组
例6.3 顺序表类模板设计 template<typenameT,int size>classseqlist { T slist[size]; //存放顺序表的数组 intMaxsize; //最大可容纳项数 int last; //已存表项的最后位置 public: seqlist(){last=-1;Maxsize=size;} //初始化为空表 int Length() const{return last+1;} //计算表长度 int Find(T & x)const; // 寻找x在表中位置(下标) boolIsIn(T & x); //判断x是否在表中 bool Insert(T & x,int i); //x插入到列表中第i个位置处(下标) bool Remove(T & x); //删除X int Next(T & x); //寻找X的后续位置 int Prior(T & x); //寻找x的前驱位置 boolIsEmpty(){return last==-1;} //判断表是否空 boolIsFull(){return last==Maxsize -1;} //判断表是否满 T Get(inti){return i<0||i>last?NULL:slist[i];} //取第i个元素之值 T& operator[](int i); }; //重载下标运算符[] classseqlist { intslist[size]; //存放顺序表的数组,size需定义为常量 intMaxsize; //最大可容纳项数 int last; //已存表项的最后位置 public: seqlist(){last=-1;Maxsize=size;} //初始化为空表 int Length() const{return last+1;} //计算表长度 intFind(int& x)const; // 寻找x在表中位置(下标) boolIsIn(int& x); //判断x是否在表中 boolInsert(int& x,inti); //x插入到列表中第i个位置处(下标) boolRemove(int& x); //删除X intNext(int& x); //寻找X的后续位置 intPrior(int& x); //寻找x的前驱位置 boolIsEmpty(){return last==-1;} //判断表是否空 boolIsFull(){return last==Maxsize -1;} //判断表是否满 intGet(inti){return i<0||i>last?NULL:slist[i];} //取第i个元素之值 int& operator[](int i); }; //重载下标运算符[]
例6.3 顺序表类模板设计 template <typenameT,intsize> intseqlist<T,size>::Find(T & x)const{//const成员函数,表明对象的数据只能读不能写。 int i=0; while(i<=last && slist[i]!=x) i++; //顺序查找是否有x if (i>last) return -1; //未找到,返回-1 else return i; //找到,返回下标 } template <typenameT,int size> boolseqlist<T,size>::IsIn(T & x){ int i=0; bool found=0; while(i<=last && !found) //换了一种方法来查找 if (slist[i]!=x) i++; else found=1; //找到 return found;}
例6.3 顺序表类模板设计 template <typenameT,int size> T& seqlist<T,size>::operator[] (int i){ if(i<0||i>=Maxsize){ cout<<"下标出界!"<<endl; exit(1); } while(i>last) last++; //数组最大下标增长到i returnslist[i]; } 对P194作了调整! • assert(!(i<0||i>=Maxsize)); 有没有其他方式? 对P194作了调整!
例6.3 顺序表类模板设计 template <typenameT,int size> boolseqlist<T,size>:: Insert(T & x, int i) { intj; if (i<0||i>last+1||last==Maxsize -1) returnfalse; //插入位置不合理,不能插入(健壮性) else{ last++; for(j=last;j>i;j--) slist[j]=slist[j-1]; //从表最后位置向前依次后移,空出指定位置来 slist[i]=x; return true; } }
例6.3 顺序表类模板设计 template <typenameT,intsize>boolseqlist<T,size>::Remove(T & x){ inti=Find(x),j; //先去找x在哪个位置 if(i>=0){ last--;//预先将last前移一位 for(j=i;j<=last;j++) slist[j]=slist[j+1]; //依次前移,保证表连续 return true; } return false; //表中不存在x }
例6.3 顺序表类模板设计 template <typenameT,int size> intseqlist<T,size>::Next(T & x){ inti=Find(x); if(i>=0 && i<last) return i+1; //x后继位置 else return -1; //x不在表中,或在表末尾 } template<typenameT,int size> intseqlist<T,size>::Prior(T & x){ inti=Find(x); if(i>0 && i<=last) return i-1; //x前驱的位置 else return -1; }
例6.3 顺序表类模板设计 intmain(){ seqlist<int,100> seqlisti; //seqlisti的元素为整型 inti,j,k,a[10]={2,3,5,7,11,13,17,19,23,29}; for(j=0;j<10;j++)//把素数写入 if(!seqlisti.Insert(a[j],j)){ cout<<“表太小放不下了!"<<endl;break;} j=seqlisti.Length(); for(i=0;i<j;i++) cout<<seqlisti.Get(i)<<' '; cout << endl ;//打印出seqlisti.slist[]-素数表 for(j=0;j<10;j++) seqlisti[j]=0; //采用下标运算符运算 for(j=0;j<10;j++) cout<<seqlisti[j]<<' '; cout<<endl; for(j=0;j<10;j++) seqlisti[j]=a[j];
例6.3 顺序表类模板设计 seqlisti[10]=31; //检验能否增加元素,正确!! for(j=0;j<11;j++) cout<<seqlisti[j]<<' '; cout<<endl; k=7; if (seqlisti.IsIn(k)) cout<<"7在表中"<< endl; //因形参为引用,所以实参不可用整数常量7 elsecout<<"7不在表中"<<endl; k=17; if (seqlisti.Remove (k)) cout<<"删除17"<<endl; //删除17 elsecout<<"找不到17,无法删除"; j=seqlisti.Length( ) ; for (i=0;i<j;i++) cout<<seqlisti.Get(i) <<' '; //打印剩下的素数 cout<<endl;
例6.3 顺序表类模板设计 if (seqlisti.Insert(k,j-1)){ // 把素数17装回去,成功则打印 j=seqlisti.Length ( ); for (i=0;i<j;i++) cout<<seqlisti.Get(i) <<' '; cout<<endl; } cout<<"打印17后一个素数:“ <<seqlisti.Get(seqlisti.Next(k))<<endl; cout<<"打印17前一个素数:" <<seqlisti.Get(seqlisti.Prior(k))<<endl; cout<<"素数17在表中位置(下标)为:" <<seqlisti.Find(k)<<endl; if(seqlisti.IsEmpty()) cout<<"表是空的"<<endl; else cout<<"表不空"<<endl; if (seqlisti.IsFull()) cout<<"表是满的"<<endl; else cout<<"表也不满"<<endl; if (seqlisti.IsIn(k)) cout<<"素数17在表中"<<endl; return 0; }
6.1.2 类模板与数据结构—单链表 单链表类模板设计 回忆结点类: typedefintDataType; class Node { DataType info;//数据域 Node *link;//指针域 public: Node();//生成空结点的构造函数 Node(constDatatype &);//生成一般结点的构造函数 voidPrintNode(); //打印当前结点的信息域 friend class SLList;//以SLList为Node友元类,SLList可直接访问Node私有数据,比结构安全 }; 结点类模板: template <typenameDataType> class SLList; template <typenameDataType> class Node { DataType info;//数据域 Node <DataType> *link; //指针域 public: Node();//生成空结点的构造函数 Node(constDatatype &);//生成一般结点的构造函数 voidPrintNode(); //打印当前结点的信息域 friend class SLList <DataType>;//以SLList为Node友元类,SLList可直接访问Node私有数据,比结构安全 }; tail info0 info1 infon-1 ^ …… head
6.1.2 类模板与数据结构—单链表 template <typenameDataType> Node<DataType>::Node(){ link=NULL; } template <typenameDataType> Node<DataType>::Node(constDataType & data){ info=data; link=NULL; } template <typenameDataType> voidNode<DataType>:: PrintNode(){ cout<<info<<endl; } Node::Node() { link=NULL; } Node::Node(constDataType & data){ info=data; link=NULL; } voidNode::PrintNode(){ cout<<info<<endl; }
6.1.2 类模板与数据结构—单链表 链表类模板设计 class SLList{ Node *head,*tail;//链表头指针和尾指针 public: SLList();//构造函数,生成头结点(空链表) ~SLList();//析构函数 void MakeEmpty();//清空链表,只余表头结点 Node* TravFind(DataType); //搜索数据域与data相同的结点,返回该结点的地址 void PrintSLL();//打印链表的数据域 void GrowUP(constDataType &);//链表向前生长 void GrowDN(constDataType &);//链表向后生长 void RemoveAft(Node*);//删除结点后的结点 void RemoveCur(Node*); //删除指定结点 }; template <typenameDataType>class SLList{ Node <DataType> *head,*tail;//链表头指针和尾指针 public: SLList();//构造函数,生成头结点(空链表) ~SLList();//析构函数 void MakeEmpty();//清空链表,只余表头结点 Node<DataType> * TravFind(DataType); //搜索数据域与data相同的结点,返回该结点的地址 void PrintSLL();//打印链表的数据域 void GrowUP(constDataType &);//链表向前生长 void GrowDN(constDataType &);//链表向后生长 void RemoveAft(Node <DataType> *);//删除结点后的结点 void RemoveCur(Node <DataType> *); //删除指定结点 };
6.1.2 类模板与数据结构—单链表 链表类模板成员函数: template <typenameDataType>SLList<DataType>::SLList(){ head=tail=new Node<DataType> (); } template <typenameDataType>SLList<DataType>:: ~SLList(){ MakeEmpty(); delete head; head=NULL; } template <typenameDataType>voidSLList<DataType>:: MakeEmpty(){ Node<DataType>*p; while(head->link!=NULL) { //将链表结点从链中脱离 p=head->link; head->link=p->link; delete p; p=NULL; //删除(释放)脱离下来的结点 } tail=head; //表头指针与表尾指针均指向表头结点,表示空链 }
6.1.2 类模板与数据结构—单链表 template <typenameDataType>Node <DataType>* SLList<DataType>:: TravFind(DataTypekey){ Node<DataType>*p=head->link; while(p!=NULL&&p->info!=key)p=p->link; return p;//搜索成功返回该结点地址,不成功返回NULL } template <typenameDataType>void SLList<DataType>:: PrintSLL() { //显示链表 Node<DataType>* p=head->link; while(p!=NULL) { cout<<p->info<<'\t'; p=p->link; } cout<<endl; }
6.1.2 类模板与数据结构—单链表 template <typenameDataType>void SLList<DataType>:: GrowUP(constDataType& data){ Node<DataType>*p=new Node<DataType> (data); p->link=head->link; head->link=p; //新结点始终在头结点之后 } template <typenameDataType>void SLList<DataType>:: GrowDN(constDataType& data){ Node<DataType>* p=new Node<DataType>(data); tail->link=p; tail=p; tail->link=NULL; }
6.1.2 类模板与数据结构—单链表 template <typenameDataType>void SLList<DataType>:: RemoveAfter(Node<DataType>*p){ Node<DataType>*q; q=p->link; if(q!=NULL){ p->link=q->link; deleteq; q=NULL;} } template <typenameDataType>void SLList<DataType>:: RemoveCur(Node<DataType>*p){ Node<DataType>*q=head; while(q->link!=NULL && q->link!=p) q=q->link;//遍历查找 if(q->link==tail) tail=q;//已经找到末尾 RemoveAfter(q);//删除q后面的结点p }
6.1.2 类模板与数据结构—单链表 测试: voidintmain(){ SLList<int>L1; Node<int>n, *tmp; for(int j=0;j<10;j++) L1.GrowDN(j); //向后生成链表 cout<<"初始链表:"; L1.PrintSLL(); //打印表 L1.GrowUP(20);//向前插入到头结点后 cout<<"插入结点后的链表:";L1.PrintSLL(); //打印 tmp=L1.TravFind(20); //查找插入的结点 n=*tmp; cout<<"找到结点的信息域:"; n.PrintNode(); L1.RemoveCur(tmp);//删除插入的结点 cout<<"删除结点后的链表:";L1.PrintSLL();//打印 return 0; } 类到类模板的设计要点: (1)将类中潜在可变的数据类型或者常量,替换为模板参数,设计模板头; (2)查找类中包含的其他类模板,将类名后加<模板参数名表>,便于随后的实例化。
6.1.2 类模板与数据结构—栈 顺序栈类模板设计: template <typenameDataType, intsize> class Stack{ inttop; //栈顶(下标) DataType *elements; //指向动态建立的栈 intmaxSize; //栈最大容纳的元素个数 public: Stack(); //构造函数 ~Stack(){delete[ ] elements; elements=NULL;} void Push(constDataType &); //压栈, top++ DataType Pop(); //弹出,top-- DataTypeGetElem(int); //随机取数据,top不变 void MakeEmpty(){top= -1;} //清空栈 boolIsEmpty() const{return top== -1;} //判栈空 boolIsFull() const{return top==maxSize-1;} //判栈满 void PrintStack(); //输出栈内所有数据 }; class Stack{ inttop; //栈顶(下标) DataType *elements; //指向动态建立的栈 intmaxSize; //栈最大容纳的元素个数 public: Stack(constint&size=20); //构造函数, top= -1 ~Stack(){delete[ ] elements; elements=NULL;} void Push(constDataType &); //压栈, top++ DataType Pop(); //弹出,top-- DataTypeGetElem(int); //随机取数据,top不变 void MakeEmpty(){top= -1;} //清空栈 boolIsEmpty() const{return top== -1;} //判栈空 boolIsFull() const{return top==maxSize-1;} //判栈满 void PrintStack(); //输出栈内所有数据 }; 退栈 压栈 top an-1 top an-2 …… top a1 top a0 top bottom
6.1.2 类模板与数据结构—栈 template <typenameDataType , intsize > Stack<DataType, size >::Stack () { maxSize=size; top=-1; elements=newDataType [maxSize]; //建立栈空间 assert(elements!=NULL); //假定未悬空,否则分配失败,结束 } template <typenameDataType , intsize > void Stack<DataType,size>:: PrintStack(){ for(inti=0;i<=top;i++) cout<<elements[i]<<'\t'; cout<<endl; } template <typenameDataType , intsize > void Stack<DataType,size>:: Push(constDataType &data){ assert(!IsFull()); //栈满则退出程序 elements[++top]=data; //栈顶下标先加1,元素再进栈 }
6.1.2 类模板与数据结构—栈 template <typenameDataType , intsize > DataType Stack <DataType,size>:: Pop(){ assert(!IsEmpty()); //栈已空则不能退栈,退出程序 return elements[top--]; //返回栈顶元素,同时栈顶下标-1 } template <typenameDataType , intsize > DataTypeStack <DataType,size>:: GetElem(inti){ assert(i<=top&&i>=0); //超出栈有效数据区,则退出程序 return elements[i]; //返回指定元素,top不变 }
6.1.2 类模板与数据结构—栈 测试: intmain(){ inti,a[10]={0,1,2,3,4,5,6,7,8,9},b[10]; Stack <int, 10>istack(); for(i=0;i<10;i++) istack.Push(a[i]); //压栈 if(istack.IsFull()) cout<<"栈满"<<endl; istack.PrintStack(); for(i=0;i<10;i++) b[i]=istack.Pop(); if(istack.IsEmpty()) cout<<"栈空"<<endl; for(i=0;i<10;i++) cout<<b[i]<<'\t'; //注意先进后出 cout<<endl; istack.Pop(); //弹出报错 return 0; }
6.1.2 类模板与数据结构—队列 front rear tail a0 a1 an 链队实现方式 head …… …… ^ a0 a1 a2 … … an-1 rear front 链队类模板设计: Node和SLList类模板设置: template <typenameDataType> class SLListQueue; template <typenameDataType> class Node { (略) friendclass SLListQueue<DataType>; }; template <typenameDataType> class SLList{ (略) friendclass SLListQueue<DataType>; };
6.1.2 类模板与数据结构—队列 template <typenameDataType> classSLListQueue { SLList<DataType>LstQue; Node <DataType>*front,*rear; public: SLListQueue(){front=rear=LstQue.head->link;} //空链队 ~SLListQueue(){} //析构函数 boolIsEmpty(){ returnLength()==0;} //队空否? voidEnQue(constDataType &); //进队 DataTypeDeQue(); //出队 DataTypeGetFront(); //查看队头数据 voidMakeEmpty(); //置空队列 };
6.1.2 类模板与数据结构—队列 template <typenameDataType> DataTypeSLListQueue<DataType>:: DeQue(){ …… } template <typenameDataType> DataTypeSLListQueue<DataType>:: GetFront(){ …… } template <typenameDataType> voidSLListQueue<DataType>:: MakeEmpty(){ …… } 链队类模板可以继承链表类模板吗? 继承的思想不适应类模板设计;各模板独立设计,但可以使用聚合概念!
6.2 类模板与排序查找 查找(search): 按关键字(key word),在有序的数据集合(顺序表,升序或降序)中,寻找满足条件的数据。 算法:对半查找(迭代、递归)
6.2.1类模板与查找方法 mid high 20 21 23 26 29 31 37 39 high low mid low 图6.3 查找成功例 23 成功 low mid high 2 5 7 8 9 11 13 17 19 20 21 23 26 39 37 29 31 low 23 查找 20 21 23 mid high 对半查找: 以变量low和high为数据序列的首尾元素的下标,取mid= (low+ high)/2,如mid位置的元素是所查找的,则结束。如果该元素大了,则取low=mid +1, high不变,继续查找;如果该元素小了,则取 high=mid-1,low不变,继续查找。如果查到low>=high仍未找到,则失败,停止。
6.2.1类模板与查找方法 mid high mid high mid high 9 图6.4 查找失败例 low mid high 10 2 2 5 5 7 7 8 8 9 9 9 11 11 11 13 13 13 17 17 17 19 20 29 31 21 23 37 26 39 查找 low low low 注意: (1)区间收缩过程中,low=mid+1和high=mid-1非常重要,没有“+1”和“-1”时,可能数据存在却找不到。 (2)对半查找递归算法与迭代算法。
作为有序表类模板成员函数: template<typenameT,int size> intOrderedlist<T,size> :: Binarysearch (const T & x, constintlow, constint high){ int mid=-1; if (low<=high) { mid=(low+high)/2; if (slist[mid]<x) mid = Binarysearch(x,mid+1,high); //中间点小于X,查找右区间,注意mid+1 elseif(x<slist[mid]) mid=Binarysearch(x,low,mid-1); //中间点大于X,查找左区间,注意 mid-1 } returnmid;//找到返回下标;未找到但结束了,返回-1 } 【例6.4】对半查找递归算法
有序表基本元素为类Element对象 : class Element{ intkey; // 其他域省略 public: bool operator<(Element ele){return key<ele.key;} voidsetkey(intk){key=k;} void show(){cout<<key<<'\t';} }; //重载了比较运算符,元素的比较实际是元素关键字的比较 template <typenameT,int size>classOrderedlist{ intmaxsize; intlast; T slist[size]; public: Orderedlist(){last=-1;maxsize=size;} intBinarysearch(T & x,constintlow,constint high); boolInsert(T & elem,inti); void print(); // 无关成员函数省略 };
【例6.4】对半查找递归算法 template <typenameT,intsize>boolOrderedlist<T,size>:: Insert(T & elem ,int i){ intj; if(i<0||i>last+1||last==maxsize-1) return false;//”前驱后继” else{ last++; for (j=last;j>i;j--) slist[j]=slist[j-1]; slist[i]=elem; return true;} } template <typenameT,int size> voidOrderedlist<T,size>:: print(){ inti; for(i=0;i<=last;i++){ slist[i].show(); if(i%5==4) cout<<endl;} cout<<endl; }
【例6.4】对半查找递归算法 int main(){ constint h=19;inti,k=37; Orderedlist<Element,100> ordlist; int a[h]={67,61,59,53,47,43,41,37,31,29,23, 19,17,13,11,7,5,3,2}; //降序 Element n[h],elem; for(i=0;i<h;i++) n[i].setkey(a[i]);//初始化关键字 for(i=0;i<h;i++) ordlist.Insert(n[i],0); //始终在0下标位置插入,建立升序顺序表 ordlist.print(); elem.setkey(k); i=ordlist.Binarysearch(elem,0,h-1); cout<<"整数"<<k<<"在表中位置:"<<i<<endl; return 0;}
【例6.5】对半查找迭代算法 template<typenameT,int size > intOrderedlist<T,size>:: BinarySearch(constT & x) const{ int high=last, low=0, mid;// last 当前有序表最大下标 if ( last ==- 1 ) return -1; //避免空表出错 while (low<=high ) { mid = (low+high)/2; if ( x<slist[mid] ) high = mid-1; //左缩查找区间 elseif ( slist[mid]<x ) low = mid+1; // 右缩查找区间 elsereturn mid; } if ( slist[mid] != x ) mid = -1; // 未找到 return mid; }
6.2.2 常用的排序法 • 排序(sorting): • 按照数据元素的可排序数据项(关键字)的大小,排列成升序或降序的数据序列的过程。排序是查找的前提。 • 算法:插入排序(直接、对半);交换排序(冒泡排序);选择排序(直接选择排序)
直接插入排序(升序)的思想: 当取得元素s[i](i>0)时,前面的元素s[0],s[1],…, s[i-1]已经排好序,我们将s[i]的关键字与s[i-1], s[i-2],…,的关键字顺序进行比较,找到第一个比它小的,则s[i]插到该元素之后。 6.2.2 常用的排序法——直接插入排序
作Orderedlist<T,size>类成员函数,T为数组元素类型作Orderedlist<T,size>类成员函数,T为数组元素类型 template<typenameT,int size>voidOrderedlist<T,size>:: InsertSort(){ T temp; inti,j; for (i=1;i<=last;i++){ temp=slist[i]; j=i; while (j>0&&temp<slist[j-1]){ slist[j]=slist[j-1]; j--; //查找与移动同时做 } slist[j]=temp; } } 【例6.6】升序直接插入排序算法
有序表类Orderedlist<T,size>的基本元素为Element类对象,Element类定义类似(key类型改为string),略。 voidmain(){ constint h=10; Element n[h]; inti; Orderedlist<Element,100> ordlist; string mslist[h]={"cat","book","car","zoo","fish", "cab","dog","cap","fox","can"}; for(i=0;i<h;i++) n[i].setkey(mslist[i]); for(i=0;i<h;i++) ordlist.Insert(n[i],i); //建立顺序表 cout<<"未排序表:"<<endl; ordlist.print(); ordlist.InsertSort(); cout<<"已排序表:"<<endl; ordlist.print(); } 【例6.6】升序直接插入排序算法
交换排序基本思想: 按关键字两两排序,如果发生逆序则交换之,直到所有的数据都排好为止。 6.2.2 常用的排序法——交换排序 图6.6从下往上冒泡排序 冒泡排序:(1)首先从一列数据底部(下标last)开始,相邻两数据进行比较,小的放上面,一趟下来,最小的数据冒到最上面;(2)缩小区域,按同样方法继续下一趟交换;(3)如果有一趟比较中没有发生交换,则已排好序。
template<typename T, intsize> void Orderedlist<T,size>:: BubbleSort(){ boolnoswap; int i, j; T temp; for ( i=0; i<last; i++ ) { //最多做last趟 noswap=true; //“未交换”标志为真 for ( j=last; j>i; j--) { //从下往上冒泡 if ( slist[ j ] < slist[ j-1 ] ) { temp = slist[ j ]; slist[ j ] = slist[ j-1 ]; slist[ j-1 ] = temp; noswap = false; } } if ( noswap ) break; //本趟无交换,则终止算法。 } } 【例6.8】冒泡排序算法
【例6.8】冒泡排序算法 student类对象为数组的元素 class student{ intid; //学号(主关键字) int age; //年龄 string name; // 姓名 char sex; // 性别 string address; //家庭地址 float eng, phy, math, electron; //英语,物理,数学和电子成绩 public: student(){} student(int,string,char,int,string,float,float,float,float); booloperator<(student ele){return id<ele.id;}//比较符重载 void show(){ cout<<id<<'\t'<<name<<'\t'<<sex<<'\t' <<age <<'\t' <<address<<'\t'<<eng<<'\t'<<phy<<'\t'<<math<<'\t'<<electron<<endl;} };
【例6.8】冒泡排序算法 intmain(){ constinth=4; inti; Orderedlist<student,100> ordlist; student n[h]={ student(6004327,"张菲",'m',19,"北京路58号",80,85,90,78), student(6004121,"关雨",'w',19,"天津路64号",88,75,91,68), student(6004118,"刘蓓",'w',18,"上海路37号",78,95,81,88), student(6004219,"赵昀",'m',18,"重庆路95号",78,95,81,88)}; for(i=0;i<h;i++) ordlist.Insert(n[i],i); //建立顺序表 cout<<"未排序表:"<<endl; ordlist.print(); ordlist.BubbleSort(); cout<<"已排序表:"<<endl; ordlist.print(); return 0; }
选择排序(Selection Sort): 每一趟从记录中选出关键字最小的元素,顺序放在已排好序的子序列前面,直到全部记录排序完成。直接选择排序(Straight Selection Sort)是最简单方法。 6.2.2 常用的排序法——直接选择排序 [49 38 65 97 76 13 27 49’] 13 [38 65 97 76 49 27 49’] 13 27 [65 97 76 49 38 49’] 13 27 38 [97 76 49 65 49’] 13 27 38 49 [76 97 65 49’] 13 27 38 49 49’ [9765 76] 13 27 38 49 49’ 65 [9776] 13 27 38 49 49’ 65 76 97 图6.7直接选择排序的过程
【例6.9】直接选择排序 • template<typenameT,intsize>void Orderedlist<T,size>:: SelectSort(){ • int i, j, k; T temp; • for(i=0;i<last;i++){ • k=i; temp=slist[i]; • for(j=i+1;j<=last;j++)//课本j=i有误,多了趟自己比 • if(slist[j]<temp) • { k=j; temp=slist[j]; } • if ( k != i ){ • temp=slist[i]; • slist[i]=slist[k]; • slist[k]=temp; • } • } • }
Unit 8—第六章 模板 6.1 模板与数据结构 6.4 模板与类参数 6.5 函数指针与指针识别(选读) 6.2 类模板与排序查找 6.3 索引查找与指针数组