版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第九章 群体类和群体数据的组织目录9.1 函数模板与类模板9.2 线性群体9.3 群体数据的组织9.4 综合实例对个人银行账户管理程序的改进9.5 深度探索9.6 小结29.1.1 函数模板函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计。定义方法:template 函数定义模板参数表的内容类型参数:class(或typename) 标识符常量参数:类型说明符 标识符模板参数:template class 标识符39.1 函数模板与类模板4求绝对值函数的模板#include using namespace std;templateT abs(T x)
2、return x 0? -x : x;int main() int n = -5;double d = -5.5;cout abs(n) endl;cout abs(d) endl;return 0;9.1 函数模板与类模板 9.1.1 函数模板运行结果:55.5求绝对值函数的模板分析编译器从调用abs()时实参的类型,推导出函数模板的类型参数。例如,对于调用表达式abs(n),由于实参n为int型,所以推导出模板中类型参数T为int。当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:int abs(int x) return x 0 ? x : x;59.1 函数模板与类模板
3、9.1.1 函数模板例9-1函数模板的示例/9_1.cpp#include using namespace std;template /定义函数模板void outputArray(const T *array, int count) for (int i = 0; i count; i+)cout arrayi ;cout endl;69.1 函数模板与类模板 9.1.1 函数模板例9-1(续)int main() /主函数const int A_COUNT = 8, B_COUNT = 8, C_COUNT = 20;int a A_COUNT = 1, 2, 3, 4, 5, 6, 7,
4、 8 ;/定义int数组double bB_COUNT = 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8 ;/定义double数组char cC_COUNT = Welcome to see you!;/定义char数组cout a array contains: endl;outputArray(a, A_COUNT);/调用函数模板cout b array contains: endl;outputArray(b, B_COUNT);/调用函数模板cout c array contains: endl;outputArray(c, C_COUNT);/调用函
5、数模板return 0;79.1 函数模板与类模板 9.1.1 函数模板例9-1(续)运行结果如下:a array contains:1 2 3 4 5 6 7 8b array contains:1.1 2.2 3.3 4.4 5.5 6.6 7.7 8.8 c array contains:W e l c o m e t o s e e y o u !89.1 函数模板与类模板 9.1.1 函数模板9.1.2 类模板类模板的作用使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本类型的和用户自定义类型)。99.1 函
6、数模板与类模板类模板的声明类模板:template class 类名类成员声明如果需要在类模板以外定义其成员函数,则要采用以下的形式:template 类型名 类名:函数名(参数表)109.1 函数模板与类模板 9.1.2 类模板例9-2 类模板应用举例#include #include using namespace std;/ 结构体Studentstruct Student int id; /学号 float gpa; /平均分; 119.1 函数模板与类模板 9.1.2 类模板例9-2 (续)template class Store /类模板:实现对任意类型数据进行存取private:
7、T item;/ item用于存放任意类型的数据bool haveValue; / haveValue标记item是否已被存入内容public:Store();/ 缺省形式(无形参)的构造函数T &getElem();/提取数据函数void putElem(const T &x); /存入数据函数;/以下实现各成员函数。template /缺省构造函数的实现 Store:Store(): haveValue(false) 129.1 函数模板与类模板 9.1.2 类模板13例9-2 (续)template /提取数据函数的实现T &Store:getElem() /如试图提取未初始化的数据,则
8、终止程序if (!haveValue) cout No item present! endl;exit(1);/使程序完全退出,返回到操作系统。return item; / 返回item中存放的数据 template /存入数据函数的实现 void Store:putElem(const T &x) / 将haveValue 置为true,表示item中已存入数值haveValue = true;item = x;/ 将x值存入item9.1 函数模板与类模板 9.1.2 类模板14例9-2 (续)int main() Store s1, s2;s1.putElem(3);s2.putElem
9、(-7);cout s1.getElem() s2.getElem() endl;Student g = 1000, 23 ;Store s3;s3.putElem(g); cout The student id is s3.getElem().id endl;Store d;cout Retrieving object D. ;cout d.getElem() endl/由于d未经初始化,在执行函数D.getElement()过程中导致程序终止return 0;9.1 函数模板与类模板 9.1.2 类模板线性群体线性群体的概念直接访问群体-数组类顺序访问群体-链表类栈类队列类159.2 线性
10、群体群体的概念群体是指由多个数据元素组成的集合体。群体可以分为两个大类:线性群体和非线性群体。线性群体中的元素按位置排列有序,可以区分为第一个元素、第二个元素等。非线性群体不用位置顺序来标识元素。169.2 线性群体9.2.1 线性群体的概念线性群体中的元素次序与其位置关系是对应的。在线性群体中,又可按照访问元素的不同方法分为直接访问、顺序访问和索引访问。在本章我们只介绍直接访问和顺序访问。179.2 线性群体第一个元素第二个元素第三个元素最后一个元素9.2.2 直接访问群体数组类静态数组是具有固定元素个数的群体,其中的元素可以通过下标直接访问。缺点:大小在编译时就已经确定,在运行时无法修改。
11、动态数组由一系列位置连续的,任意数量相同类型的元素组成。优点:其元素个数可在程序运行时改变。vector就是用类模板实现的动态数组。动态数组类模板:例9-3(Array.h)189.2 线性群体19例9-3 动态数组类模板程序#ifndef ARRAY_H#define ARRAY_H#include template /数组类模板定义class Array private:T* list;/用于存放动态分配的数组内存首地址int size;/数组大小(元素个数)public:Array(int sz = 50);/构造函数Array(const Array &a);/拷贝构造函数Array(
12、);/析构函数Array & operator = (const Array &rhs); /重载=“T & operator (int i); /重载”const T & operator (int i) const;operator T * ();/重载到T*类型的转换operator const T * () const;int getSize() const;/取数组的大小void resize(int sz);/修改数组的大小;9.2 线性群体 9.2.2 直接访问群体数组类template Array:Array(int sz) /构造函数assert(sz = 0);/sz为数组
13、大小(元素个数),应当非负size = sz;/ 将元素个数赋值给变量sizelist = new T size;/动态分配size个T类型的元素空间template Array:Array() /析构函数delete list;/拷贝构造函数template Array:Array(const Array &a) size = a.size; /从对象x取得数组大小,并赋值给当前对象的成员/为对象申请内存并进行出错检查list = new Tsize;/ 动态分配n个T类型的元素空间for (int i = 0; i size; i+) /从对象X复制数组元素到本对象 listi = a.l
14、isti;209.2 线性群体 9.2.2 直接访问群体数组类例9-3(续)/重载=运算符,将对象rhs赋值给本对象。实现对象之间的整体赋值template Array &Array:operator = (const Array& rhs) if (&rhs != this) /如果本对象中数组大小与rhs不同,则删除数组原有内存,然后重新分配if (size != rhs.size) delete list;/删除数组原有内存size = rhs.size;/设置本对象的数组大小list = new Tsize;/重新分配n个元素的内存/从对象X复制数组元素到本对象 for (int i
15、= 0; i size; i+)listi = rhs.listi;return *this;/返回当前对象的引用219.2 线性群体 9.2.2 直接访问群体数组类例9-3(续)/重载下标运算符,实现与普通数组一样通过下标访问元素,并且具有越界检查功能template T &Array:operator (int n) assert(n = 0 & n size);/检查下标是否越界return listn;/返回下标为n的数组元素template const T &Array:operator (int n) const assert(n = 0 & n size);/检查下标是否越界re
16、turn listn;/返回下标为n的数组元素/重载指针转换运算符,将Array类的对象名转换为T类型的指针template Array:operator T * () return list;/返回当前对象中私有数组的首地址229.2 线性群体 9.2.2 直接访问群体数组类例9-3(续)template Array:operator const T * () const return list;/返回当前对象中私有数组的首地址/取当前数组的大小template int Array:getSize() const return size;/ 将数组大小修改为sztemplate void A
17、rray:resize(int sz) assert(sz = 0);/检查sz是否非负if (sz = size)/如果指定的大小与原有大小一样,什么也不做return;T* newList = new T sz;/申请新的数组内存int n = (sz size) ? sz : size;/将sz与size中较小的一个赋值给n/将原有数组中前n个元素复制到新数组中for (int i = 0; i n; i+)newListi = listi;delete list;/删除原数组list = newList;/ 使list指向新数组size = sz;/更新size#endif /ARRA
18、Y_H239.2 线性群体 9.2.2 直接访问群体数组类例9-3(续)24数组类模板的构造函数/ 构造函数template Array:Array(int sz) /sz为数组大小(元素个数),应当非负assert(sz = 0);/ 将元素个数赋值给变量sizesize = sz;/动态分配size个T类型的元素空间list = new T size;9.2 线性群体 9.2.2 直接访问群体数组类25数组类模板的拷贝构造函数/拷贝构造函数template Array:Array(const Array &a) /从对象x取得数组大小,并赋值给当前对象的成员size = a.size;/为
19、对象申请内存并进行出错检查list = new Tsize;/ 动态分配n个T类型的元素空间/从对象X复制数组元素到本对象 for (int i = 0; i size; i+)listi = a.listi;9.2 线性群体 9.2.2 直接访问群体数组类26浅拷贝9.2 线性群体 9.2.2 直接访问群体数组类template Array:Array(const Array& x) size = x.size; list = x.list;int main() Array a(10); . Array b(a); . list sizeaa的数组元素占用的内存拷贝前 list sizeaa
20、的数组元素占用的内存拷贝后 list sizeb27深拷贝9.2 线性群体 9.2.2 直接访问群体数组类 list sizeaa的数组元素占用的内存拷贝前 list sizeaa的数组元素占用的内存拷贝后 list sizebb的数组元素占用的内存28数组类模板的重载=运算符函数/重载“=”运算符template Array &Array:operator = (const Array& rhs) if (&rhs != this) if (size != rhs.size) delete list;/删除数组原有内存size = rhs.size;/设置本对象的数组大小list = new
21、 Tsize;/重新分配n个元素的内存/从对象X复制数组元素到本对象 for (int i = 0; i size; i+)listi = rhs.listi;return *this;/返回当前对象的引用9.2 线性群体 9.2.2 直接访问群体数组类29数组类模板的重载下标操作符函数template T &Array:operator (int n) assert(n = 0 & n size);/越界检查return listn; /返回下标为n的数组元素template const T &Array:operator (int n) const assert(n = 0 & n siz
22、e); /越界检查return listn; /返回下标为n的数组元素9.2 线性群体 9.2.2 直接访问群体数组类为什么有的函数返回引用如果一个函数的返回值是一个对象的值,就不应成为左值。如果返回值为引用。由于引用是对象的别名,通过引用当然可以改变对象的值。309.2 线性群体 9.2.2 直接访问群体数组类31重载指针转换操作符template Array:operator T * () return list;/返回私有数组的首地址template Array:operator const T * () const return list;/返回私有数组的首地址9.2 线性群体 9.2
23、.2 直接访问群体数组类指针转换运算符的作用#include using namespace std;void read(int *p, int n) for (int i = 0; i pi;int main() int a10; read(a, 10); return 0;#include Array.h#include using namespace std;void read(int *p, int n) for (int i = 0; i pi;int main() Array a(10); read(a, 10); return 0;329.2 线性群体 9.2.2 直接访问群体数
24、组类Array类的应用例9-4求范围2N中的质数,N在程序运行时由键盘输入。339.2 线性群体 9.2.2 直接访问群体数组类34#include #include #include Array.husing namespace std;int main() Array a(10);/ 用来存放质数的数组,初始状态有10个元素。int n, count = 0;cout = 2 as upper limit for prime numbers: ;cin n;for (int i = 2; i = n; i+) bool isPrime = true;for (int j = 0; j co
25、unt; j+)if (i % aj = 0) /若i被aj整除,说明i不是质数isPrime = false; break;if (isPrime) if (count = a.getSize() a.resize(count * 2);acount+ = i;for (int i = 0; i count; i+)cout setw(8) ai;cout endl;return 0;9.2 线性群体 9.2.2 直接访问群体数组类例9-4(续)9.2.3 顺序访问群体链表类链表是一种动态数据结构,可以用来表示顺序访问的线性群体。链表是由系列结点组成的,结点可以在运行时动态生成。每一个结点包
26、括数据域和指向链表中下一个结点的指针(即下一个结点的地址)。如果链表每个结点中只有一个指向后继结点的指针,则该链表称为单链表。359.2 线性群体36单链表9.2 线性群体 9.2.3 顺序访问群体链表类 data1 data2 data3 datan NULLheadrear37单链表的结点类模板template class Node private: Node *next;public: T data; Node(const T& item,Node* next = 0); void insertAfter(Node *p); Node *deleteAfter(); Node *next
27、Node() const; 9.2 线性群体 9.2.3 顺序访问群体链表类38在结点之后插入一个结点9.2 线性群体 9.2.3 顺序访问群体链表类 data1 data2 p datatemplate void Node:insertAfter(Node *p) /p节点指针域指向当前节点的后继节点 p-next = next; next = p; /当前节点的指针域指向p 39 删除结点之后的结点9.2 线性群体 9.2.3 顺序访问群体链表类 data1 data2 data3tempPtrNode *Node:deleteAfter(void) Node *tempPtr = nex
28、t; if (next = 0) return 0; next = tempPtr-next; return tempPtr; 例9-5结点类模扳/Node.h#ifndef NODE_H#define NODE_H/类模板的定义template class Node private:Node *next;/指向后继结点的指针public:T data;/数据域Node (const T &data, Node *next = 0); /构造函数void insertAfter(Node *p);/在本结点之后插入一个同类结点p Node *deleteAfter();/删除本结点的后继结点,
29、并返回其地址Node *nextNode();/获取后继结点的地址const Node *nextNode() const; /获取后继结点的地址;409.2 线性群体 9.2.3 顺序访问群体链表类/类的实现部分/构造函数,初始化数据和指针成员template Node:Node(const T& data, Node *next/* = 0 */) : data(data), next(next) /返回后继结点的指针template Node *Node:nextNode() return next;/返回后继结点的指针template const Node *Node:nextNode
30、() const return next; 419.2 线性群体 9.2.3 顺序访问群体链表类例9-5(续)/在当前结点之后插入一个结点p template void Node:insertAfter(Node *p) p-next = next; /p结点指针域指向当前结点的后继结点 next = p; /当前结点的指针域指向p /删除当前结点的后继结点,并返回其地址template Node *Node:deleteAfter() Node *tempPtr = next;/将欲删除的结点地址存储到tempPtr中if (next = 0)/如果当前结点没有后继结点,则返回空指针retu
31、rn 0;next = tempPtr-next;/使当前结点的指针域指向tempPtr的后继结点return tempPtr;/返回被删除的结点的地址#endif /NODE_H429.2 线性群体 9.2.3 顺序访问群体链表类例9-5(续)链表的基本操作生成结点插入结点查找结点删除结点遍历链表清空链表439.2 线性群体 9.2.3 顺序访问群体链表类例9-6 链表类模板#ifndef LINKEDLIST_H#define LINKEDLIST_H#include Node.htemplate class LinkedList private:/数据成员:Node *front, *r
32、earNode *prevPtr, *currPtr; int size;int position;Node *newNode(const T &item,Node *ptrNext=NULL);void freeNode(Node *p);void copy(const LinkedList& L);public:LinkedList();LinkedList(const LinkedList &L); LinkedList();LinkedList & operator = (const LinkedList &L); int getSize() const;bool isEmpty()
33、const;void reset(int pos = 0void next();bool endOfList() const;int currentPosition(void) const;void insertFront(const T &item);void insertRear(const T &item);void insertAt(const T &item);void insertAfter(const T &item);T deleteFront();void deleteCurrent();T& data();const T& data() constvoid clear();
34、#endif /LINKEDLIST_H449.2 线性群体 9.2.3 顺序访问群体链表类例9-7 链表类应用举例/9_7.cpp#include #include LinkedList.husing namespace std;int main() LinkedList list;for (int i = 0; i item;list.insertFront(item);cout List: ;list.reset();while (!list.endOfList() cout list.data() ;list.next();cout endl;int key;cout key;list
35、.reset();while (!list.endOfList() if (list.data() = key) list.deleteCurrent();list.next();cout List: ;list.reset();while (!list.endOfList() cout list.data() ;list.nextcout endl;return 0;459.2 线性群体 9.2.3 顺序访问群体链表类例9-7(续)运行结果如下:3 6 5 7 5 2 4 5 9 10List: 10 9 5 4 2 5 7 5 6 3Please enter some integer ne
36、eded to be deleted: 5List: 10 9 4 2 7 6 3469.2 线性群体 9.2.3 顺序访问群体链表类9.2.4 栈类栈是只能从一端访问的线性群体,可以访问的这一端称栈顶,另一端称栈底。479.2 线性群体ana2a1入栈出栈栈顶栈底栈的应用举例表达式处理489.2 线性群体 9.2.4 栈类ba/a/b+c*d(a)t1+a/b+c*dt1=a/b(b)dct1*+a/b+c*d(c)t3a/b+c*dt3=t1+t2(e)t2t1+a/b+c*dt2=c*d(d)栈的基本状态栈空栈中没有元素栈满栈中元素个数达到上限一般状态栈中有元素,但未达到栈满状态499.
37、2 线性群体 9.2.4 栈类509.2 线性群体 9.2.4 栈类50栈顶ana1a0入栈出栈数组下标maxn10一般状态栈顶入栈出栈数组下标初始状态(栈空)maxn10栈顶amaxana1a0入栈出栈数组下标maxn10栈满状态50栈的基本操作初始化入栈出栈清空栈访问栈顶元素检测栈的状态(满、空)519.2 线性群体 9.2.4 栈类例9-8 栈类模板/Stack.h#ifndef STACK_H#define STACK_H#include template class Stack private:T listSIZE;int top;public:Stack();void push(c
38、onst T &item);T pop();void clear();const T &peek() const;bool isEmpty() const;bool isFull() const;529.2 线性群体 9.2.4 栈类例9-8 (续)/模板的实现template Stack:Stack() : top(-1) template void Stack:push(const T &item) assert(!isFull();list+top = item;template T Stack:pop() assert(!isEmpty();return listtop-;templa
39、te const T &Stack:peek() const assert(!isEmpty();return listtop;/返回栈顶元素template bool Stack:isEmpty() const return top = -1;template bool Stack:isFull() const return top = SIZE - 1;template void Stack:clear() top = -1;#endif/STACK_H539.2 线性群体 9.2.4 栈类栈的应用例9.9 一个简单的整数计算器实现一个简单的整数计算器,能够进行加、减、乘、除和乘方运算。使
40、用时算式采用后缀输入法,每个操作数、操作符之间都以空白符分隔。例如,若要计算3+5则输入3 5 +。乘方运算符用表示。每次运算在前次结果基础上进行,若要将前次运算结果清除,可键入c。当键入q时程序结束。Calculator.h Calculator.cpp 9_9.cpp549.2 线性群体 9.2.4 栈类55例9-9/Calculator.h#ifndef CALCULATOR_H#define CALCULATOR_H#include Stack.h/ 包含栈类模板定义文件class Calculator /计算器类private:Stack s;/ 操作数栈void enter(dou
41、ble num);/将操作数num压入栈/连续将两个操作数弹出栈,放在opnd1和opnd2中bool getTwoOperands(double &opnd1, double &opnd2);void compute(char op);/执行由操作符op指定的运算public:void run();/运行计算器程序void clear();/清空操作数栈;#endif /CALCULATOR_H9.2 线性群体 9.2.4 栈类56例9-9 (续)/Calculator.cpp#include Calculator.h#include #include #include using name
42、space std;/工具函数,用于将字符串转换为实数inline double stringToDouble(const string &str) istringstream stream(str);/字符串输入流double result;stream result;return result;void Calculator:enter(double num) /将操作数num压入栈s.push(num);9.2 线性群体 9.2.4 栈类57例9-9 (续)bool Calculator:getTwoOperands(double &opnd1, double &opnd2) if (s
43、.isEmpty() /检查栈是否空cerr Missing operand! endl;return false;opnd1 = s.pop();/将右操作数弹出栈if (s.isEmpty() /检查栈是否空cerr Missing operand! endl;return false;opnd2 = s.pop();/将左操作数弹出栈return true;9.2 线性群体 9.2.4 栈类58void Calculator:compute(char op) /执行运算double operand1, operand2;bool result = getTwoOperands(opera
44、nd1, operand2); if (result) /如果成功,执行运算并将运算结果压入栈switch(op) case +: s.push(operand2 + operand1); break;case -: s.push(operand2 - operand1); break;case *: s.push(operand2 * operand1); break;case /:if (operand1 = 0) /检查除数是否为0cerr Divided by 0! endl;s.clear();/除数为0时清空栈 elses.push(operand2 / operand1);bre
45、ak;case : s.push(pow(operand2, operand1); break;default:cerr Unrecognized operator! endl;break;cout = s.peek() str, str != q) switch(str0) case c: s.clear(); break;case -: /遇-需判断是减号还是负号if (str.size() 1)enter(stringToDouble(str);elsecompute(str0);break;case +:/遇到其它操作符时case *:case /:case :compute(str0
46、);default: /若读入的是操作数,转换为整型后压入栈enter(stringToDouble(str); break;void Calculator:clear() /清空操作数栈s.clear(); 9.2 线性群体 9.2.4 栈类例9-9 (续)60例9-9 (续)/9_9.cpp#include Calculator.hint main() Calculator c;c.run();return 0;9.2 线性群体 9.2.4 栈类9.2.5 队列类队列是只能向一端添加元素,从另一端删除元素的线性群体619.2 线性群体a1 a2an-1 an队头队尾入队出队a0队列的基本状
47、态队空队列中没有元素队满队列中元素个数达到上限一般状态队列中有元素,但未达到队满状态629.2 线性群体 9.2.5 队列类639.2 线性群体 9.2.5 队列类a0 a1an-1 an队头队尾入队出队数组下标 0 1 n-1 n max(一般状态)队头队尾入队出队数组下标 0 1 n-1 n max(队空状态) a0 a1 an-1 an amax队头队尾入队出队数组下标 0 1 n-1 n max(队满状态)元素移动方向元素移动方向63循环队列在想象中将数组弯曲成环形,元素出队时,后继元素不移动,每当队尾达到数组最后一个元素时,便再回到数组开头。649.2 线性群体 9.2.5 队列类6
48、59.2 线性群体 9.2.5 队列类1234m-1m-2m-30amam+1am+2a3队头队尾a4am-2am-3am-1队满状态 元素个数=m1234m-1m-2m-30队尾队头队空状态 元素个数=0队尾1234m-1m-2m-30a0a1a2a3队头一般状态65例9-10 队列类模板/Queue.h#ifndef QUEUE_H#define QUEUE_H#include /类模板的定义template class Queue private:int front, rear, count;/队头指针、队尾指针、元素个数T listSIZE;/队列元素数组public:Queue();
49、 /构造函数,初始化队头指针、队尾指针、元素个数void insert(const T &item);/新元素入队T remove();/元素出队void clear();/清空队列const T &getFront() const;/访问队首元素669.2 线性群体 9.2.5 队列类/测试队列状态int getLength() const;/求队列长度bool isEmpty() const;/判队队列空否bool isFull() const;/判断队列满否;/构造函数,初始化队头指针、队尾指针、元素个数template Queue:Queue() : front(0), rear(0)
50、, count(0) template void Queue:insert (const T& item) /向队尾插入元素assert(count != SIZE);count+;/元素个数增1listrear = item;/向队尾插入元素rear = (rear + 1) % SIZE;/队尾指针增1,用取余运算实现循环队列template T Queue:remove() assert(count != 0);int temp = front;/记录下原先的队首指针 count-;/元素个数自减 front = (front + 1) % SIZE;/队首指针增1。取余以实现循环队列
51、return listtemp;/返回首元素值679.2 线性群体 9.2.5 队列类例9-10(续)template const T &Queue:getFront() const return listfront;template int Queue:getLength() const /返回队列元素个数return count;template bool Queue:isEmpty() const /测试队空否return count = 0;template bool Queue:isFull() const /测试队满否return count = SIZE;template voi
52、d Queue:clear() /清空队列count = 0;front = 0; rear = 0; #endif /QUEUE_H689.2 线性群体 9.2.5 队列类例9-10(续)9.3 群体数据的组织插入排序选择排序交换排序顺序查找折半查找699.3 群体数据的组织排序(sorting)排序是计算机程序设计中的一种重要操作,它的功能是将一个数据元素的任意序列,重新排列成一个按关键字有序的序列。数据元素:数据的基本单位。在计算机中通常作为一个整体进行考虑。一个数据元素可由若干数据项组成。关键字:数据元素中某个数据项的值,用它可以标识(识别)一个数据元素。在排序过程中需要完成两种基本操
53、作:比较两个数的大小调整元素在序列中的位置709.3 群体数据的组织内部排序与外部排序内部排序:待排序的数据元素存放在计算机内存中进行的排序过程。外部排序:待排序的数据元素数量很大,以致内存存中一次不能容纳全部数据,在排序过程中尚需对外存进行访问的排序过程。719.3 群体数据的组织内部排序方法插入排序选择排序交换排序729.3 群体数据的组织插入排序的基本思想每一步将一个待排序元素按其关键字值的大小插入到已排序序列的适当位置上,直到待排序元素插入完为止。739.3 群体数据的组织 9.3.1 插入排序初始状态: 5 4 10 20 12 3插入操作:1 4 4 5 10 20 12 32 1
54、0 4 5 10 20 12 33 20 4 5 10 20 12 34 12 4 5 10 12 20 35 3 3 4 5 10 12 20直接插入排序在插入排序过程中,由于寻找插入位置的方法不同又可以分为不同的插入排序算法,这里我们只介绍最简单的直接插入排序算法。例9-11 直接插入排序函数模板(9_11.h)749.3 群体数据的组织 9.3.1 插入排序75例9-11 直接插入排序函数模板template void insertionSort(T a, int n) int i, j;T temp;for (int i = 1; i 0 & temp aj - 1) aj = aj
55、- 1;j-;aj = temp;9.3 群体数据的组织 9.3.1 插入排序选择排序的基本思想每次从待排序序列中选择一个关键字最小的元素,(当需要按关键字升序排列时),顺序排在已排序序列的最后,直至全部排完。769.3 群体数据的组织 9.3.2 选择排序5 4 10 20 12 3初始状态:3 4 10 20 12 53 4 10 20 12 5第 i 次选择后,将选出的那个记录与第 i 个记录做交换。3 4 5 20 12 10.直接选择排序在选择类排序方法中,从待排序序列中选择元素的方法不同,又分为不同的选择排序方法,其中最简单的是通过顺序比较找出待排序序列中的最小元素,称为直接选择排
56、序。例9-12 直接选择排序函数模板(9-12.h)779.3 群体数据的组织 9.3.2 选择排序78例9-12 直接选择排序函数模板template void mySwap(T &x, T &y) T temp = x;x = y;y = temp;template void selectionSort(T a, int n) for (int i = 0; i n - 1; i+) int leastIndex = i;for (int j = i + 1; j n; j+)if (aj aleastIndex)leastIndex = j;mySwap(ai, aleastIndex)
57、;9.3 群体数据的组织 9.3.2 选择排序交换排序的基本思想两两比较待排序序列中的元素,并交换不满足顺序要求的各对元素,直到全部满足顺序要求为止。799.3 群体数据的组织 9.3.3 交换排序最简单的交换排序方法起泡排序对具有n个元素的序列按升序进行起泡排序的步骤:首先将第一个元素与第二个元素进行比较,若为逆序,a则将两元素交换。然后比较第二、第三个元素,依次类推,直到第n-1和第n个元素进行了比较和交换。此过程称为第一趟起泡排序。经过第一趟,最大的元素便被交换到第n个位置。对前n-1个元素进行第二趟起泡排序,将其中最大元素交换到第n-1个位置。如此继续,直到某一趟排序未发生任何交换时,
58、排序完毕。对n个元素的序列,起泡排序最多需要进行n-1趟。809.3 群体数据的组织 9.3.3 交换排序起泡排序举例对整数序列 8 5 2 4 3 按升序排序819.3 群体数据的组织 9.3.3 交换排序8524352438243582345823458初始状态第一趟结果第二趟结果第三趟结果第四趟结果小的逐渐上升每趟沉下一个最大的例9-13 起泡排序函数模板template void mySwap(T &x, T &y) T temp = x;x = y;y = temp;template void bubbleSort(T a, int n) int i = n 1;while (i 0
59、) int lastExchangeIndex = 0; for (int j = 0; j i; j+) if (aj + 1 aj) mySwap(aj, aj + 1); lastExchangeIndex = j; i = lastExchangeIndex;829.3 群体数据的组织 9.3.3 交换排序9.3.4 顺序查找其基本思想从序列的首元素开始,逐个元素与待查找的关键字进行比较,直到找到相等的。若整个序列中没有与待查找关键字相等的元素,就是查找不成功。顺序查找函数模板例9-14839.3 群体数据的组织84例9-14 顺序查找函数模板template int seqSearc
60、h(const T list, int n, const T &key) for(int i = 0; i n; i+)if (listi = key)return i; return -1; 9.3 群体数据的组织 9.3.4 顺序查找折半查找的基本思想对于已按关键字排序的序列,经过一次比较,可将序列分割成两部分,然后只在有可能包含待查元素的一部分中继续查找,并根据试探结果继续分割,逐步缩小查找范围,直至找到或找不到为止。859.3 群体数据的组织 9.3.5 折半查找折半查找举例用折半查找法,在下列序列中查找值为21的元素:869.3 群体数据的组织 9.3.5 折半查找L=1513192
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 慢性胃炎的护理教育与培训
- 护理质量改进的最佳实践
- 楼房承包销售合同
- 核桃苗木销售合同
- 护理教育理念研修汇报
- 护理人员的沟通与协调能力
- 2026年活动策划执行托管协议
- 2026年物联网租赁数据资产管理合同
- 2026年独家天使投资合同书
- 2026年一站式翻译服务合同
- 2026中国民用航空飞行学院招聘事业编制硕士辅导员25人考试备考题库及答案解析
- 2026年中国中车集团法务岗面试常见问题及合同法实务解析
- 2026年山东医学高等专科学校辅导员招聘笔试备考试题及答案解析
- 电梯维修动火作业安全规范手册
- 2026江西江钨控股集团本部招聘审计专业管理人员3人笔试历年备考题库附带答案详解
- 纪检干部个人现实表现材料-范本模板
- 我国微生物肥料产业化发展:现状、挑战与突破路径研究
- 工程监理平行检验台帐
- 国企资产管理培训课件
- 火龙罐疗法临床操作规范与应用指南
- 纺织厂建设项目投资可行性分析报告
评论
0/150
提交评论