1 / 74

2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

第 2 章 线性表. 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示. 本章重点难点. 重点 : (1) 线性表 ADT 顺序存储实现中的基本操作及相关算法; (2)ADT 链式存储实现中基本操作及相关算法; (3) 双向链表的基本操作及相关算法; (4) 循环链表的特点、基本操作及相关算法。 难点 : 线性表 ATD 的设计和实现,线性表 ADT 链式存储实现,包括双向链表、循环链表的基本操作和有关算法。. 第 2 章 线性表. 2.1 线性表的类型定义

steffi
Télécharger la présentation

2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

  2. 本章重点难点 重点: (1) 线性表ADT顺序存储实现中的基本操作及相关算法;(2)ADT链式存储实现中基本操作及相关算法;(3)双向链表的基本操作及相关算法;(4)循环链表的特点、基本操作及相关算法。 难点: 线性表ATD的设计和实现,线性表ADT链式存储实现,包括双向链表、循环链表的基本操作和有关算法。

  3. 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

  4. 2.1 线性表的类型定义 • 线性表的定义 线性表是n 个类型相同数据元素的有限序列, 通常记作(a1, a2, a3, …, an )。 • 线性结构的基本特征为: (1) 集合中必存在唯一的一个“第一元素”; (2) 集合中必存在唯一的一个“最后元素”; (3)除最后元素在外,均有唯一的后继; (4)除第一元素之外,均有唯一的前驱。

  5. 2.1 线性表的类型定义 • 线性结构的基本特征为: ADT List { D={ ai | ai ∈ElemSet, i=1,2,...,n, n≥0 } {称 n为线性表的表长; 称n=0时的线性表为空表。} 数据对象: 数据关系: R1={ <ai-1 ,ai >|ai-1 ,ai∈D, i=2,...,n } 基本操作: 见下页 }ADT List

  6. 2.1 线性表的类型定义 • 基本操作 InitList( &L ) //构造一个空的线性表L。 DestroyList( &L ) //销毁L ListEmpty( L ) //判断L是否空 ListLength( L ) //求L的长度 PriorElem( L, cur_e, &pre_e ) //求前驱的值 NextElem( L, cur_e, &next_e ) //求后继的值

  7. 2.1 线性表的类型定义 • 基本操作 GetElem( L, i, &e ) //取i位置的值 LocateElem( L, e, compare( ) ) //在线性表中查找e ListTraverse(L, visit( )) //遍历线性表 ClearList( &L ) //清空线性表 ListInsert( &L, i, e ) //在i位置插入e ListDelete(&L, i, &e) //删除i位置的元素

  8. 2.1 线性表的类型定义 • 基本操作的应用 用定义过的基本操作实现例2-1,例2-2 例 2-1 假设:有两个集合 A 和 B 分别用两个线性表 LA 和 LB 表示,即:线性表中的数据元素即为集合中的成员。 现要求一个新的集合A=A∪B。

  9. 2.1 线性表的类型定义 • 例2-1操作步骤: (1) 从线性表LB中依次察看每个数据元素; GetElem(LB, i,&e) (2) 依值在线性表LA中进行查访; LocateElem(LA, e, equal( )) (3) 若不存在,则插入之。 ListInsert(LA, n+1, e)

  10. 2.1 线性表的类型定义 • 例2-1算法 void union(List &La, List Lb) { La_len = ListLength(La); // 求线性表的长度 Lb_len = ListLength(Lb); for (i = 1; i <= Lb_len; i++) { ……………………………. } }

  11. 2.1 线性表的类型定义 • 例2-1算法 GetElem(Lb, i, e); // 取Lb中第i个数据元素赋给e if (!LocateElem(La, e, equal( )) ) ListInsert(La, ++La_len, e); // La中不存在和 e 相同的数据元素,则插入之 • 例2-1算法时间复杂性 O(ListLength(La)*ListLength(Lb))

  12. 2.1 线性表的类型定义 • 基本操作的应用 用定义过的基本操作实现例2-2 例 2-2 将两个“数据元素按值递增有序排列”的线性表La和Lb归并到线性表Lc,且Lc具有同样的性质。 设 La=(a1,…ai,….an) Lb=(b1,…bj,….bm) Lc=(c1,…ck,…cm+n)

  13. 2.1 线性表的类型定义 • 例2-2算法 void MergeList(List La, List Lb, List &Lc) { } // merge_list InitList(Lc); // 构造空的线性表 Lc i = j = 1; k = 0; La_len = ListLength(La); Lb_len = ListLength(Lb); while ((i <= La_len) && (j <= Lb_len)) { // La 和 Lb 均不空 } while (i<=La_len) // 若 La 不空 while (j<=Lb_len) // 若 Lb 不空 见下页

  14. 2.1 线性表的类型定义 • 例2-2算法 GetElem(La, i, ai); GetElem(Lb, j, bj); if (ai <= bj) { // 将 ai 插入到 Lc 中 ListInsert(Lc, ++k, ai); ++i; } else { // 将 bj 插入到 Lc 中 ListInsert(Lc, ++k, bj); ++j; }

  15. 2.1 线性表的类型定义 • 例2-2算法 while (i <= La_len) { // 当La不空时 GetElem(La, i++, ai); ListInsert(Lc, ++k, ai); } // 插入 La 表中剩余元素 while (j <= Lb_len) { // 当Lb不空时 GetElem(Lb, j++, bj); ListInsert(Lc, ++k, bj); } // 插入 Lb 表中剩余元素

  16. 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

  17. 2.2 线性表的顺序表示和实现 存储线性表,就是要保存至少两类信息:(1) 线性表中的数据元素;(2) 线性表中数据元素的顺序关系; 如何在计算机中存储线性表? 如何在计算机中实现线性表的 基本操作?

  18. 2.2 线性表的顺序表示和实现 • 线性表的顺序表示的定义 以数据元素x 的存储位置和数据元素 y 的存储位置之间的某种关系表示逻辑关系<x,y>。 线性表的顺序表示最简单的一种顺序映象方法是:令x的存储位置和y 的存储位置相邻。

  19. 2.2 线性表的顺序表示和实现 • 线性表的顺序表示图示 用一组地址连续的存储单元依次存放线性表中的数据元素 a1 a2 … ai-1 ai … an 线性表的起始地址 称作线性表的基地址

  20. 2.2 线性表的顺序表示和实现 • 数据元素地址之间的关系 以“存储位置相邻”表示有序对<ai-1,ai>时, ai-1和ai的地址关系如下: LOC(ai) = LOC(ai-1) + C C为一个数据元素所占存储量 所有数据元素的存储位置均取决于第一个数据元素的存储位置。 LOC(ai) = LOC(a1) + (i-1)×C ↑基地址

  21. 2.2 线性表的顺序表示和实现 • 顺序表示的实现 #define LIST_INIT_SIZE 80 // 线性表存储空间的初始分配量 #define LISTINCREMENT 10 // 线性表存储空间的分配增量 typedef struct { } SqList; // 俗称 顺序表 ElemType *elem;// 存储空间基址 int length;// 当前长度 int listsize;// 当前分配的存储容量 // (以sizeof(ElemType)为单位)

  22. 2.2 线性表的顺序表示和实现 • 基本操作的实现 Status InitList_Sq( SqList &L ) { // 构造一个空的线性表 } // InitList_Sq L.elem = (ElemType*) malloc (LIST_ INIT_SIZEsizeof (ElemType)); if (!L.elem) exit(OVERFLOW); L.length = 0; L.listsize = LIST_INIT_SIZE; return OK;

  23. 2.2 线性表的顺序表示和实现 • 基本操作的实现 线性表操作 ListInsert(&L, i, e)的实现: 首先分析: 插入元素时, 线性表的逻辑结构发生什么变化?

  24. 2.2 线性表的顺序表示和实现 • 插入操作过程示意图

  25. 2.2 线性表的顺序表示和实现 • 插入操作算法 Status ListInsert_Sq(SqList &L, int i, ElemType e) { // 在顺序表L的第 i 个元素之前插入新的元素e } // ListInsert_Sq …… q = &(L.elem[i-1]); // q 指示插入位置 for (p = &(L.elem[L.length-1]); p >= q; --p) *(p+1) = *p; // 插入位置及之后的元素右移 *q = e; // 插入e ++L.length; // 表长增1 return OK;

  26. 2.2 线性表的顺序表示和实现 • 插入操作算法 if (i < 1 || i > L.length+1) return ERROR; // 插入位置不合法 if (L.length >= L.listsize) { // 当前存储空间已满,增加分配 newbase = (ElemType *)realloc(L.elem, (L.listsize+LISTINCREMENT)*sizeof (ElemType)); if (!newbase) exit(OVERFLOW); L.elem = newbase; // 新基址 L.listsize += LISTINCREMENT; }

  27. 2.2 线性表的顺序表示和实现 • 插入算法时间复杂性分析 设在第i个元素之前插入的概率为pi,则在长度为n的线性表中插入一个元素时所需平均移动元素次数为: 若假定在任何一个位置上插入元素的概率相同,则平均移动次数为: O(n)

  28. 2.2 线性表的顺序表示和实现 • 基本操作的实现 线性表删除操作ListDelete(&L, i, &e)的实现: 首先分析: 删除元素时, 线性表的逻辑结构发生什么变化?

  29. 2.2 线性表的顺序表示和实现 • 删除操作过程示意图

  30. 2.2 线性表的顺序表示和实现 • 删除操作过程示意图 Status ListDelete_Sq (SqList &L, int i, ElemType &e) { } // ListDelete_Sq if ((i < 1) || (i > L.length)) return ERROR; p = &(L.elem[i-1]); // p 为被删除元素的位置 e = *p; // 被删除元素的值赋给 e q = L.elem+L.length-1; // 表尾元素的位置 for (++p; p <= q; ++p) *(p-1) = *p; --L.length;// 表长减1 return OK;

  31. 2.2 线性表的顺序表示和实现 • 删除操作时间复杂性分析 设删除第i个元素的概率为pi,则在长度为n的线性表中删除一个元素时所需平均移动次数为: 若假定在任何一个位置上删除元素的概率相同,则平均移动次数为: O(n)

  32. 2.2 线性表的顺序表示和实现 • 顺序表的优缺点 (1) 优点 a.节省存储空间; b.对线性表中第i个结点的操作易于实现; c.容易查找一个结点的前驱和后继。 (2)缺点 a.插入和删除操作比较困难; b.建立空表时,较难确定所需的存储空间。

  33. 第2章 线性表 2.1 线性表的类型定义 2.2 线性表的顺序表示和实现 2.3 线性表的链式表示和实现 2.4 一元多项式的表示

  34. 2.3 线性表的链式表示和实现 2.3.1 单链表 2.3.2 静态链表 2.3.3 循环链表 2.3.4 双向链表

  35. 2.3.1 单链表 • 链表的定义 一个线性表由若干个结点组成,每个结点至少含有两个域:数据域(信息域)和指针域(链域),由这样的结点形成存储的线性表称作链表。 • 单链表结构示意图

  36. 2.3.1 单链表 • 单链表结构示意图 • 结构特点 逻辑次序和物理次序相同; 元素之间的逻辑关系用表示;需要额外空间存储元素之间的关系; 是不是随机存储结构? 不一定 指针 不是

  37. 2.3.1 单链表 • 头指针的概念 在链式存储结构中以第一个结点的存储地址作为线性表的基地址,通常称它为头指针。 线性表的最后一个数据元素没有后继,因此最后一个结点中的"指针"是一个特殊的值 "NULL",通常称它为"空指针"。

  38. 2.3.1 单链表 • 头结点的概念 在单链表上设置一个结点,它本身不存放数据,它的指针域指向第一个元素的地址。 • 头结点的作用 使对第一个元素的操作与对其它元素的操作保持一致。

  39. 2.3.1 单链表 • 单链表的C语言实现 Typedef struct LNode { ElemType data;// 数据域 struct Lnode *next;// 指针域 } LNode, *LinkList; LinkList L; // L 为单链表的头指针

  40. 2.3.1 单链表 • 单链表操作的实现 GetElem_L(LinkList L, int i, ElemType &e) //查找第i个结点,将第i个结点的值存入e • 查找过程 (1)从第一个结点p开始,j=1开始记数; (2)当p->next不为空时,转向下一个继续记数; (3)直到j=i或p->next为空。

  41. 2.3.1 单链表 • GetElem_L算法 Status GetElem_L(LinkList L, int i, ElemType &e) { } p = L->next; j = 1; // p指向第一个结点,j为计数器 while (p && j<i) { p = p->next; ++j; } if ( !p) return ERROR; // 第 i 个元素不存在 e = p->data; // 取得第 i 个元素 return OK;

  42. 2.3.1 单链表 • 单链表操作的实现 Status ListInsert_L(LinkList L, int i, ElemType e) // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 e • 插入过程 (1)查找第i-1个结点p; (2)生成结点s,存入e; (3)s->netx=p->next, p->next=s;

  43. 2.3.1 单链表 • ListInsert_L算法 Status ListInsert_L(LinkList L, int i, ElemType e) { // L 为带头结点的单链表的头指针,本算法 // 在链表中第i 个结点之前插入新的元素 e } // LinstInsert_L p = L; j = 0; while (p && j < i-1) { p = p->next; ++j; } // 寻找第 i-1 个结点 if (!p ) return ERROR; // i 大于表长或者小于1 ……

  44. 2.3.1 单链表 • ListInsert_L算法 s = (LinkList) malloc ( sizeof (LNode)); // 生成新结点 s->data = e; s->next = p->next; p->next = s; // 插入 return OK; • ListInsert_L算法的时间杂性 O(ListLength(L))

  45. 2.3.1 单链表 • 单链表操作的实现 ListDelete_L(LinkList L, int i, ElemType &e) // L 为带头结点的单链表的头指针,本算法 // 删除链表中第i 个结点,值储入 e • 删除过程 (1) 查找第i-1个结点p; (2) q=p->netx,p->next=q->next (3) free(q)

  46. 2.3.1 单链表 • ListDelete_L算法 Status ListDelete_L(LinkList L, int i, ElemType &e) { } // ListDelete_L p = L; j = 0; while (p->next && j < i-1) { p = p->next; ++j; } if (!(p->next) ) return ERROR; // 删除位置不合理 q = p->next; p->next = q->next; e = q->data; free(q); return OK;

  47. 2.3.1 单链表 • 单链表应用举例 例 2-3 将两个“数据元素按值递增有序排列”的线性表La和Lb归并到线性表Lc,且Lc具有同样的性质。 设 La=(a1,…ai,….an) Lb=(b1,…bj,….bm) Lc=(c1,…ck,…cm+n)

  48. 2.3.1 单链表 • 例2-3算法 Status MergeList_L(LinkList &La,LinkList &Lb,LinkList &Lc) {LinkList pa=La->next,pb=Lb->next,pc=Lc=La; while(pa&&pb) { if(pa->data<=pb->data) {pc->next=pa;pc=pa;pa=pa->next;} else {pc->next=pb;pc=pb;pb=pb->next;} } pc->next=pa?pa:pb; free(Lb); } // MergeList_L

  49. 2.3.1 单链表 • 链表的优缺点 (1) 优点 a. 插入和删除时间复杂性低; b.不需预先分配空间。 (2)缺点 a.指针占用存储空间,增加了内存负担。

  50. 2.3 线性表的链式表示和实现 2.3.1 单链表 2.3.2 静态链表 2.3.3 循环链表 2.3.4 双向链表

More Related