1、南京邮电大学计算机学院 陈慧南 2006年9月,数据结构,Data Structures in C+,南京邮电大学计算机学院 陈慧南 2006年9月,第2章 线性表,南京邮电大学计算机学院 陈慧南 2006年9月,2.1 线性表ADT 2.2 线性表的顺序表示 2.3 线性表的链接表示 2.4 多项式的算术运算,南京邮电大学计算机学院 陈慧南 2006年9月,2.1 线性表ADT,南京邮电大学计算机学院 陈慧南 2006年9月,线性表的定义线性表是n(0)个元素a0,a1,an-1 的线性序列,记为: (a0,a1,an-1)。其中n是线性表中元素的个数,称为线性表的长度;n=0时称为空表。a
2、i是表中下标为i的元素(i=0,1,n-1),称ai是ai+1的直接前驱元素,ai+1是ai的直接后继元素。 线性表是动态数据结构,它的表长可以改变。,南京邮电大学计算机学院 陈慧南 2006年9月,线性表ADT ADT LinearList 数据:0个或多个元素的线性序列(a0,a1,.,an-1),其最大允许长度为MaxListSize。 运算:Create(): 创建一个空线性表。Destroy():撤消一个线性表。IsEmpty():若线性表空,则返回true;否则返回false。Length(): 返回表中元素个数。,南京邮电大学计算机学院 陈慧南 2006年9月,Find(i,x)
3、:在x中返回表中下标为i的元素ai。若不存在,则返回false,否则返回true。 Search(x):若x不在表中,则返回-1,否则返回x在表中的下标。 Insert(i,x):在元素ai之后插入x。若i=-1,则x插在第一个元素a0前。若插入成功,则返回true,否则返回false。 Delete(i):删除元素ai。若删除成功,则返回true,否则返回false。 Update(i,x):将元素ai的值修改为x。若修改成功,则返回true,否则返回false。 Output(out):把表送至输出流 / 插入x 到表:(a0,a1,.,an-1),南京邮电大学计算机学院 陈慧南 2006
4、年9月,线性表类 template class LinearList public: virtual bool Find(int i,T,南京邮电大学计算机学院 陈慧南 2006年9月,2.2 线性表的顺序表示,南京邮电大学计算机学院 陈慧南 2006年9月,2.2.1 顺序存储结构,顺序存储表示是用一组地址连续的存储单元依次存储线性表中元素。顺序表顺序表示的线性表称为顺序表,南京邮电大学计算机学院 陈慧南 2006年9月,地址计算公式若已知顺序表中每个元素占k个存储单元,第一个元素a0在计算机内存中的首地址是loc(a0),则表中任意一个元素ai在内存中的存储地址loc(ai)为loc(ai
5、)=loc(a0)+i*k随机存取结构只要给定loc(a0)和k,就可以确定线性表中任意一个元素的存储地址,换句话说,顺序表是一种随机存取结构。,南京邮电大学计算机学院 陈慧南 2006年9月,2.2.2 顺序表类,顺序表类 template class SeqList:public LinearList public: /公有函数SeqList(int mSize);SeqList() delete elements; bool Find(int i,T,南京邮电大学计算机学院 陈慧南 2006年9月, private:/私有数据int maxLength; /顺序表的最大长度T *elem
6、ents; /动态一维数组的指针 ;,南京邮电大学计算机学院 陈慧南 2006年9月,动态存储分配 构造函数,构建一个空线性表 template SeqList:SeqList(int mSize) maxLength=mSize;elements=new TmaxLength; n=0; ,南京邮电大学计算机学院 陈慧南 2006年9月,析构函数,撤消一个顺序表 template SeqList: SeqList() delete elements; ,南京邮电大学计算机学院 陈慧南 2006年9月,2.2.3 线性表运算实现,搜索运算Find(i,x): 查找下标为i的元素ai。在x中返回
7、表中下标为i的元素ai (即表中 第i+1个元素)。如果不存在,则返回false,否则返回true。,x=elementsi; 渐近时间复杂度:O(1),南京邮电大学计算机学院 陈慧南 2006年9月,template bool SeqList:Find(int i,T ,南京邮电大学计算机学院 陈慧南 2006年9月,插入运算Insert(i,x):在表中下标为i的元素ai后插入x。若i=-1,则将新元素x插在最前面。若插入成功,返回true;,南京邮电大学计算机学院 陈慧南 2006年9月,插入运算的平均时间复杂度 分析:设顺序表长度为n,共有n+1个可插入元素的位置,并设在各位置处插入元
8、素的概率是相等的,即Pi=1/(n+1),在位置i(i=-1,0,n-1)后插入一个元素要移动 n-i-1个元素。,南京邮电大学计算机学院 陈慧南 2006年9月,template bool SeqList:Insert(int i,T x) /在元素ai之后插入x if (in-1) /越界检查couti;j-) elementsj+1=elementsj; elementsi+1=x;n+; return true; ,南京邮电大学计算机学院 陈慧南 2006年9月,删除运算Delete(i): 删除元素ai。,南京邮电大学计算机学院 陈慧南 2006年9月,删除运算的平均时间复杂度 分析
9、: 设顺序表长度为n,则删除元素ai(i=0,n-1),要移动n-i-1元素。若删除表中每个元素的概率是相等的,即Qi=1/n,,南京邮电大学计算机学院 陈慧南 2006年9月,template bool SeqList:Delete(int i) /删除元素ai if (!n) /下溢出检查coutn-1) cout“Out Of Bounds“endl; return false; /从前往后逐个前移元素for (int j=i+1;jn;j+) elementsj-1=elementsj; n-; return true; ,南京邮电大学计算机学院 陈慧南 2006年9月,void ma
10、in() int x=10;SeqList r(4);r.Insert(-1,x); r.Insert(-1,x); r.Output(cout); /? 请复习C+,理解这一函数 ,南京邮电大学计算机学院 陈慧南 2006年9月,线性表的顺序存储表示的优缺点 优点:随机存取;存储空间利用率高。 缺点:插入、删除效率低;必须按事先估计的最大元素个数分配连续的存储空间,难以临时扩大。,南京邮电大学计算机学院 陈慧南 2006年9月,2.3 线性表的链接表示,南京邮电大学计算机学院 陈慧南 2006年9月,2.3.1 单链表,链接存储表示 单链表的结点结构单链表结构,南京邮电大学计算机学院 陈慧南
11、 2006年9月,注意事项 头指针first是指向单链表的头结点的指针 最后一个结点的指针域为,地址值为0 逻辑上相邻的元素在物理上不一定相邻 不能出现“断链”现象,南京邮电大学计算机学院 陈慧南 2006年9月,结点类 #include “linearlist.h“ template class SingleList;/超前声明 template class Node private:T element;Node *link;friend class SingleList; ;,南京邮电大学计算机学院 陈慧南 2006年9月,单链表类 template class SingleList:pu
12、blic LinearList public:SingleList() first=NULL; n=0; SingleList();bool Find(int i,T,南京邮电大学计算机学院 陈慧南 2006年9月,. private:Node* first; ;,顺序表类SeqList、单链表类SingleList是抽象线性表类LinearList类的派生类。,南京邮电大学计算机学院 陈慧南 2006年9月,构造函数SingleList() first=NULL; n=0; 析构函数template SingleList: SingleList() Node *p;while (first)
13、 p=first-link;delete first;first=p; ,南京邮电大学计算机学院 陈慧南 2006年9月,搜索运算必须从头指针开始沿链逐个计数查找,称为顺序查找搜索运算的平均、最坏的渐近时间复杂度:O(n),南京邮电大学计算机学院 陈慧南 2006年9月,template bool SingleList:Find(int i,T ,南京邮电大学计算机学院 陈慧南 2006年9月,插入运算 修改两个指针域的值插入渐近时间复杂度:O(1)q-link=p-link;p-link=q;,南京邮电大学计算机学院 陈慧南 2006年9月,插入运算步骤:生成数据域为x的新结点,q指向新结点
14、;从first开始找第i+1个结点,p指向该结点;将q插入p之后。表长加1。,南京邮电大学计算机学院 陈慧南 2006年9月,template bool SingleList:Insert(int i,T x) if (in1) cout * q=new Node;q-element=x; Node *p=first; / 找ai元素所在的结点pfor (int j=0; jlink;,first,i=2,南京邮电大学计算机学院 陈慧南 2006年9月,if(i1) q-link=p-link; /新结点q插在p之后p-link=q;else q-link=first; /新结点q插在头结点之
15、前 first=q;n+; return true; / 删除结点p是指删除指针变量p所指示的结点*p。,南京邮电大学计算机学院 陈慧南 2006年9月,单链表的删除只需修改一个指针“q-link=p-link”,但还需使用“delete p;”语句回收结点占用的空间。,南京邮电大学计算机学院 陈慧南 2006年9月,单链表的步骤从first开始找第i+1个结点,p指向该结点,q指向p之前驱结点;从单链表中删除p;释放p之空间;表长减1。,南京邮电大学计算机学院 陈慧南 2006年9月,template bool SingleList:Delete(int i) if ( !n ) coutn
16、-1 ) cout *p=first,*q=first;for (int j=0; jlink;,南京邮电大学计算机学院 陈慧南 2006年9月,if (i=0) first=first-link;/ 删除头结点else p=q-link; q-link=p-link;delete p; n-;return true; ,南京邮电大学计算机学院 陈慧南 2006年9月,单链表运算的优缺点优点 单链表插入和删除只需修改一两个指针,无需移动元素。如已知前驱结点,插入删除运算的时间为O(1)可以动态分配结点空间,线性表的长度只受内存大小限制。 缺点查找运算费时,只能顺序查找,不能随机查找,南京邮电大
17、学计算机学院 陈慧南 2006年9月,2.3.2 带表头结点的单链表,请区分“表头结点”和“头结点”,南京邮电大学计算机学院 陈慧南 2006年9月,template HeaderList: HeaderList() Node *first=new Node; first-link=NULL;n=0; ,南京邮电大学计算机学院 陈慧南 2006年9月,template bool HeaderList:Insert(int i, T x) if (in1) cout *p=first; for (int j=0; jlink;Node * q=new Node;q-element=x;q-lin
18、k=p-link; p-link=q;n+;return true; ,南京邮电大学计算机学院 陈慧南 2006年9月,template bool HeaderList:Delete(int i) if ( !n ) coutn1 ) cout *q=first, *p; for (int j=0; jlink;p=q-link; q-link=p-link; delete p; n-; return true; ,南京邮电大学计算机学院 陈慧南 2006年9月,2.3.3 单循环链表,南京邮电大学计算机学院 陈慧南 2006年9月,2.3.4 双向链表,南京邮电大学计算机学院 陈慧南 200
19、6年9月,结点类 template class DoubleList; /超前声明 template class DNode private:T element;DNode *lLink, *rLink;friend DoubleList; ;,南京邮电大学计算机学院 陈慧南 2006年9月,插入操作的核心步骤如下: (1)DNode *q=new DNode; q-element=x; (2)q-lLink=p-lLink; q-rLink=p; p-lLink-rLink=q; p-lLink=q;,错误:p-lLink-rLink=q; q-lLink=p-lLink;q-rLink=p
20、; p-lLink=q;,南京邮电大学计算机学院 陈慧南 2006年9月,删除操作的核心步骤如下: (1)p-lLink-rLink=p-rLink; p-rLink-lLink=p-lLink; (2)delete p;,南京邮电大学计算机学院 陈慧南 2006年9月,2.4 多项式的算术运算,多项式相加p(x)=3x148x8+6x2+2 q(x)=2x10+4x86x2 q(x)p(x)+q(x) 结果:q(x) =3x14+2x104x8+2,南京邮电大学计算机学院 陈慧南 2006年9月,多项式的逻辑结构:视为线性表p(x)=3x14-8x8+6x2+2数据元素 (coef,exp)
21、 表示多项式项 coefxexp ,coef是该项的系数,exp是变元x的指数。,南京邮电大学计算机学院 陈慧南 2006年9月,多项式的存储表示p(x)=3x14-8x8+6x2+2( (3,14),(-8,8),(6,2),(2,0) )顺序表示线性表长度事先难以确定;算术运算需插入和删除元素。,南京邮电大学计算机学院 陈慧南 2006年9月,多项式的链接表示多项式的项,南京邮电大学计算机学院 陈慧南 2006年9月,2.4.1 项结点类,项结点类 Term* InsertAfter(int c,int e)构造一个新项(c,e)结点,插在*this项之后,函数返回新项结点的地址。,南京邮
22、电大学计算机学院 陈慧南 2006年9月,class Term public:Term(int c,int e); /构造函数1Term(int c,int e,Term* nxt); /构造函数2Term* InsertAfter(int c,int e); private:int coef;int exp;Term *link;friend ostream ,南京邮电大学计算机学院 陈慧南 2006年9月,构造函数 Term:Term(int c,int e):coef(c),exp(e) link=0; Term:Term(int c,int e,Term *nxt):coef(c),e
23、xp(e) link=nxt; Term:Term(int c,int e) coef=c;exp=e;link=0; ,南京邮电大学计算机学院 陈慧南 2006年9月,InsertAfter函数实现 Term* Term:InsertAfter(int c,int e) link=new Term(c,e,link); return link; 调用语句:q=q-InsertAfter(c,e);,南京邮电大学计算机学院 陈慧南 2006年9月,重载输出运算符 ostream ,南京邮电大学计算机学院 陈慧南 2006年9月,2.4.3 多项式的C+类,class Polynominal p
24、ublic:Polynominal(); Polynominal();void AddTerms(istream /多项式相加,南京邮电大学计算机学院 陈慧南 2006年9月,private:Term* theList; /单循环链表的表头指针friend ostream ,南京邮电大学计算机学院 陈慧南 2006年9月,2.4.4 多项式类的实现,构造函数 Polynominal:Polynominal() theList=new Term(0,1); theList-link=theList; ,南京邮电大学计算机学院 陈慧南 2006年9月,2.4.5 多项式的输入和输出,输入多项式 v
25、oid Polynominal: AddTerms(istream ,南京邮电大学计算机学院 陈慧南 2006年9月,输出多项式 void Polynominal:Output(ostream ,南京邮电大学计算机学院 陈慧南 2006年9月,多项式相加,南京邮电大学计算机学院 陈慧南 2006年9月,若p-exp=q-exp,则同类项合并,令q-coef=q-coef+p-coef;如果此时有q-coef=0,则从q(x)中删除结点*q,指针q指向原*q的后继,指针p指向下一项;否则,指针p、q和q1均后移一项。 若 p-expq-exp,则复制*p,新结点插在 *q1与*q之间,指针q1指
26、向新结点,指针q不动,而指针p指向下一项。 若 p-expexp,则将q指示的当前项保留在q(x)中,所以令指针q1和q后移一项,指针p不动。,南京邮电大学计算机学院 陈慧南 2006年9月,void Polynominal:PolyAdd(Polynominal,南京邮电大学计算机学院 陈慧南 2006年9月,if(p-exp=q-exp) q-coef=q-coef+p-coef;if(q-coef=0) q1-link=q-link; delete(q); q=q1-link; else q1=q; q=q-link; else q1=q1-InsertAfter(p-coef,p-exp); p=p-link;/while (p-exp=0) ,