310 likes | 481 Views
线性表. 线性结构. 存在唯一的一个被称作 “ 第一个 ” 的数据元素 存在唯一一个被称作 “ 最后一个 ” 的元素 除第一个外,每个元素有唯一的前驱 除最后一个外,每个元素有唯一的后继. 线性表 — 具有线性结构的数据. InitList DestoryList ClearList ListEmpty ListLength GetElem LocateElem PriorElem NextElem ListInsert ListDelete ListTraverse. MergeList 合并两个(有序)线性表.
E N D
线性结构 • 存在唯一的一个被称作“第一个”的数据元素 • 存在唯一一个被称作“最后一个”的元素 • 除第一个外,每个元素有唯一的前驱 • 除最后一个外,每个元素有唯一的后继
线性表—具有线性结构的数据 • InitList DestoryList ClearList • ListEmpty ListLength • GetElem LocateElem • PriorElem NextElem • ListInsert ListDelete • ListTraverse
MergeList 合并两个(有序)线性表 void mergelist(List La, List Lb, List &Lc) //已知La,Lb中的数据按值升序排列 //合并La,Lb到新的Lc,Lc也按升序排列 { InitList(Lc); i=j=1;k=0; La_len=ListLength(La); Lb_len=ListLength(Lb);
while(i<=La_len && j<=Lb_len) { GetElem(La,i,ai); GetElem(Lb,j,bj); if(ai<bj) { k++; ListInsert(Lc,k,ai); i++; } else { k++; ListInsert(Lc,k,bj); j++; } }
while(i<=La_len) { GetElem(La,i,ai); k++; ListInsert(Lc,k,ai); } while(j<=Lb_len) { GetElem(Lb,j,bj); k++; ListInsert(Lc,k,bi); } }
List面向对象的表示方式 class List { public: // constructors and destructor: List(); // 构造函数 List(const List& aList); // copy 构造函数 ~List(); // 析构函数 // list operations: bool isEmpty() const; //判断list是否为空 //前条件:无 //后条件:如果list是空的,则返回 true,否则 返回false int getLength() const; //返回list的当前长度 //前条件:无 //后条件:返回当前list的长度
void insert(int index, ListItemType newItem); // 在位置 index的地方插入一个数据项 newItem. // 前条件: index 表示期望newItem应该在插入好后的list的位置. // 后条件: 如果1<=index<=getLength()+1, 则newItem应该在插入后的list // 的index位置,它后面的数据将依次后移;否则 不进行任何处理 void remove(int index); // 删除给定位置的元素. // 前条件: index 表示期望删除元素的位置 // 后条件: 如果 1 <= index <= getLength(), // 在位置index的元素将被删除,后面的元素依次前移; // 如果1> index 或者index> getLength() 时,不进行任何处理 ListItemType retrieve(int index) const; // 按照位置返回元素的值. // 前条件: index 是要取回的元素的位置 // 后条件: 如果 1 <= index <= getLength(),则返回值为 // index位置的元素,否则返回ListItemType的默认值 private: …. }
其他操作 • ClearList • LocateElem • PriorElem • NextElem • ListTraverse 都可由前面的操作实现
不同存储方式下的不同实现 线性存储 class List{ .. .. .. private: ListItemType pl[MAXNUM]; int size;// 记录现有的数据个数 }
线性存储下主要方法的实现 bool List::isEmpty() const; int List::getLength() const; void List::insert(int index, ListItemType newItem); void List::remove(int index); ListItemType List::retrieve(int index) const;
链式存储 class List{ .. .. .. private: struct ListNode //链表节点类型 { ListItemType item; // 线性表中一个数据 ListNode *next; // 下一个数据节点 }; // end struct int size; // 线性表中数据个数 ListNode *head; // 头节点而指针 }
链式存储下主要方法的实现 bool List::isEmpty() const; int List::getLength() const; void List::insert(int index, ListItemType newItem); void List::remove(int index); ListItemType List::retrieve(int index) const;
其他形式的链表 • 循环链表 • 双向链表
关于C++中指针的一点儿补充 Sometype *p; • 分配空间 p= new Sometype; //做完这句,如果分配不到空间,p将为NULL //p=(Sometype*)malloc(sizeof(Sometype)) • 释放空间 delete p; // free(p);
如果是分配多个空间 Sometype *p; • 分配空间 p= new Sometype[arraysize]; //做完这句,如果分配不到空间,p将为NULL //p=(Sometype*)malloc(sizeof(arraysize*Sometype)); • 释放空间 delete [] p;
C++中的模版 • 如果一个函数或者类的定义中,可以把某类型抽象出来,也就是说,这个函数或者类的定义适合多种类型,可以考虑使用模版。 • 例: void swap(int &i, int &j) { int temp=i; i=j; j=temp; }
//可以用模版改成 template <class T> void swap(T &i, T &j) { T temp=i; i=j; j=temp; } //则可以这样使用 double r=8,s=9; swap(r,s); int m=4,n=5; swap(m,n);
类模版的使用 • 如果用模版定义了一个类,例如叫 list, 则可按照下述方式使用 list<int> a,b; //a,b 为在list模版中用int替换以后得到的类的类型的变量 list<int> func(list<char> c, list<bool>d); //func 的返回值类型为 list<int>, 需要两个参数,分别为list<char>和list<bool>类型
C++中list/vector 介绍 • 所在头文件 list <list> vector <vector>
#include <list> #include <iostream> using namespace std ; typedef list<int> LISTINT; void main() { LISTINT listOne; LISTINT listAnother; LISTINT::iterator i; // Add some data listOne.push_front (2); listOne.push_front (1); listOne.push_back (3);
listAnother.push_front(4); listAnother.assign(listOne.begin(), listOne.end()); // 1 2 3 for (i = listAnother.begin(); i != listAnother.end(); ++i) cout << *i << " "; cout << endl; listAnother.assign(4, 1); // 1 1 1 1 for (i = listAnother.begin(); i != listAnother.end(); ++i) cout << *i << " "; cout << endl; listAnother.erase(listAnother.begin()); // 1 1 1
for (i = listAnother.begin(); i != listAnother.end(); ++i) cout << *i << " "; cout << endl; listAnother.erase(listAnother.begin(), listAnother.end()); if (listAnother.empty()) cout << "All gone\n";} 程序输出为: 1 2 3 1 1 1 1 1 1 1 All gone
//front, back 的例子 #include <list> #include <string> #include <iostream> using namespace std ; typedef list<string> LISTSTR; void main(){ LISTSTR test; test.push_back("back"); test.push_front("middle"); test.push_front("front"); // front cout << test.front() << endl; // back cout << test.back() << endl; test.pop_front(); test.pop_back(); // middle cout << test.front() << endl; }
程序输出为: front back middle
//insert的例子 #include <list> #include <iostream> using namespace std ; typedef list<int> LISTINT; void main(){ int rgTest1[] = {5,6,7}; int rgTest2[] = {10,11,12}; LISTINT listInt; LISTINT listAnother; LISTINT::iterator i; // Insert one at a time listInt.insert (listInt.begin(), 2); listInt.insert (listInt.begin(), 1); listInt.insert (listInt.end(), 3); // 1 2 3 for (i = listInt.begin(); i != listInt.end(); ++i) cout << *i << " "; cout << endl; // Insert 3 fours listInt.insert (listInt.end(), 3, 4); // 1 2 3 4 4 4
for (i = listInt.begin(); i != listInt.end(); ++i) cout << *i << " "; cout << endl; // Insert an array in there listInt.insert (listInt.end(), rgTest1, rgTest1 + 3); // 1 2 3 4 4 4 5 6 7 for (i = listInt.begin(); i != listInt.end(); ++i) cout << *i << " "; cout << endl; // Insert another LISTINT listAnother.insert (listAnother.begin(), rgTest2, rgTest2+3); listInt.insert (listInt.end(), listAnother.begin(), listAnother.end()); // 1 2 3 4 4 4 5 6 7 10 11 12 for (i = listInt.begin(); i != listInt.end(); ++i) cout << *i << " "; cout << endl; }
程序输出为: 1 2 3 1 2 3 4 4 4 1 2 3 4 4 4 5 6 7 1 2 3 4 4 4 5 6 7 10 11 12
List使用的例子 请思考下:多项式的表示和加法运算(乘法运算) struct item{ int power; double coefficient; }; typedef list<item> Poly; Poly operator+(const Poly& a, const Poly &b);
作业: Poly operator+(const Poly& a, const Poly &b) 的算法应如何设计? Poly operator*(const Poly& a, const Poly &b) 的算法应如何设计?