150 likes | 225 Views
2 、线性表. 1 、线性结构的定义:. 空或者只有一个结点。或者 1 、存在唯一的一个被称之为”第一个“ 的结点。 2 、存在唯一的一个被称之为”最后一个“ 的结点。 3 、除第一个结点之外,每个结点均只有一个前驱结点。 4 、除最后一个结点之外,每个结点均只有一个后继结点。 分为以下几大类: · 线性表: 进通过它们之间的相对位置,确定它们之间的相互关系的线性结构。 e.g: 序列: a 1 、 a 2 、 a 3 …………………a n-1 、 a n · 分类表 · 时间有序表 · 频率有序表 · 序列. 2 、线性表.
E N D
2、线性表 • 1、线性结构的定义: • 空或者只有一个结点。或者 1、存在唯一的一个被称之为”第一个“ 的结点。 • 2、存在唯一的一个被称之为”最后一个“ 的结点。 • 3、除第一个结点之外,每个结点均只有一个前驱结点。 • 4、除最后一个结点之外,每个结点均只有一个后继结点。 • 分为以下几大类: • ·线性表:进通过它们之间的相对位置,确定它们之间的相互关系的线性结构。 • e.g: 序列:a1、 a2、 a3…………………an-1、 an • ·分类表 • ·时间有序表 • ·频率有序表 • ·序列
2、线性表 • 2、基本操作:插入、删除、查找 …… • e.g:已知线性表 LA 和线性表 LB 中的结点为递增序。将 LA 和 LB 进行合并至 • 另一线性表 LC, 并仍为递增序。 • LA = (3,5,8,11) LB = (2,6,8,9,11,15,20) • LC = (2,3,5,6,8,8,9,11,11,15,20) Void Mergelist(List La,list Lb, list & Lc) { InitiList( 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 ) { Listinsert(Lc, ++k, ai ) ; ++i; } else { Listinsert(Lc, ++k, bj ) ; ++j; } } while (i <= La.len) { GetElem(La,i,ai); Listinsert(Lc, ++k, ai ) ; ++i; }; while (j <= Lb.len) { GetElem(Lb,j,bj); Listinsert(Lc, ++k, bj ) ; ++j; }; } // Mergelist La Lb • 时间复杂性: O( m + n )
2、线性表 • 3、物理存储位置的计算: ·顺序表示:在物理位置上紧靠在一起。如用数组表示线性表。 • ·设第一个结点的存储地址为 LOC(a1), 余类推。设每个结点占用 L 个单元。则: • LOC(ai) = LOC(ai-1) + L • = LOC(ai-2) + 2L • = LOC(ai-(i-1)) + (i-1)L • = LOC(a1) + (i-1)L a1 a2 ai-1 ai an
2、线性表 • 4、插入的时间复杂性分析: • 在一般情况下,插在第 i 个结点之前,移动 n-(i-1) 次 • 插在第 1 个结点之前,移动 n 次 • 插在第 2 个结点之前,移动 n-1 次 • 插在第 i 个结点之前,移动 n-(i-1) 次 • 插在第 n 个结点之前,移动 1 次。 • 插在第 n 个结点之后,移动 0 次。 总共 n+1 种情况 • ·在长度为 n 的顺序表示的线性表中插入一个结点的平均次数为: • ∑(n-i+1)/(n+1) = n/2 时间复杂性为 O(n)。 n i =1
2、线性表 • 5、删除的时间复杂性分析: • 在一般情况下,删除第 i 个结点,移动 n-i 次 • 删除第 1 个结点,移动 n-1 次 • 删除第 2 个结点,移动 n-2 次 • 删除第 i 个结点,移动 n-i 次 • 删除第 n 个结点,移动 0 次。 总共 n 种情况 • ·在长度为 n 的顺序表示的线性表中删除一个结点的平均次数为: • ∑(n-i)/n = (n-1)/2 时间复杂性为 O(n)。 n i =1 • ·另外,通过 KEY 查找结点,代价 O(n)。 • 查找第 i 个结点,代价O(1)。
data next data next L 头结点:不是线性表 之中的结点。但增加 此结点后,操作容易。 A H A B B Z ∧ Z ∧ 2、线性表 • 6、线性链表(单链接表): • · 结点的表示:参照下图所示的情况: typedef struct Lnode { ElemType dat a; struct Lnode * next; } Lnode, * LinkList; • · 单链接表的表示:参照下图所示的情况: 其中H 是表首指针。
2、线性表 • 6、线性链表(单链接表): • · 和顺序表示的线性表的操作的比较: 插入: O(1) 删除: O(1) FINDith: O(i) 平均 O(n) FINDkey : 平均 O(n) 插入: O(n) 删除: O(n) FINDith: O(1) FINDkey : 平均 O(n) 单链表 顺序存储的线性表
2、线性表 • 7、静态链表的使用 • 目的:在顺序存储(数组)的情况下,利用链表的插、删操作快速功能。 • 使用环境:用于不支持动态存储分配功能的语言。当然也可用于支持动态存储分配功 • 能的语言。 • 缺点:必须预估存区的大小,造成浪费。 • 手段:采用备用链或空闲栈实现。使用者必须自己编写分配单元和回收无用单元的操 作。使用单元时,自备用链分配。无用单元被回收到备用链。 data cur data cur 0 1 data cur 2 space[0] 1 space[1] 2 3 4 5 space[2] 3 space[3] 6 4 space[4] -1 5 space[5] 6 space[6] -1
2、线性表 • 将用作存储空间的数组的所有单元分配至空闲栈或备用链。 void InitSpace_SL(SLinkList & Space) { for ( i=0; i < MAXSIZE -1; ++i ) space[i].cur = i+1; space[MAXSIZE-1] = 0; } • 从空闲栈或备用链得到可用的数组单元,其下标为 i。 int Malloc_SL(SLinkList &Space) { i = space[0].cur; if ( space[0].cur); space[0].cur = space[i].cur; return i; } • 将下标为 k 的无用的数组单元回收至空闲栈或备用链。 int free_SL(SLinkList &Space, int k) { space[k].cur = space[0].cur; space[0].cur = k; }
2、线性表 • 8、双向链表: • · 特点:结点的有两个指针场用于指向本结点的前驱结点和后继结点。前驱结点的后继结 点和后继结点的前驱结点都是本结点。知道了本结点的地址就可以把它删除。 L typedef struct duLnode { ElemType data; struct duLnode * prior; struct duLnode * next; } duLnode, * duLinkList;
2、线性表 • 8、双向链表: • · 删除:给出待删结点的地址就可以把它删除。如;删除数据场之值为 a 的结点,地址由 p 给出。 L a b c p 执行:p->prior->next = p->next ; 执行:p->next->prior = p->prior ; 最后执行: free(p) 查找:可从两头开始。代价从平均 n/2 降低为 n/4。
s 2、线性表 • 8、双向链表: • · 插入:注意插入次序。如:将数据场为 x 的结点,插在由指针 p 指向的结点之后。 p L a b c x ·s->prior = p; ·s->next = p->next; ·p->next->prior = s; ·p->next = s;
2、线性表 • 例如:一元多项式的表示及相加; • ·如:多项式: PA = 7+3x+9x8+5x17 PB = 8x+22x7-9x8 typedef struct Lnode { ElemType data; struct Lnode * next; } Lnode, * LinkList; typedef struct { flost coef; int expn; } term, ElemType; coef expn next PA ∧ 7 0 3 1 9 8 5 17 PB ∧ 8 1 22 7 -9 8 PC 7 0 11 1 227 ∧ 5 17 • ·算法:指数等:若系数之和为零,则两首结点都删除。否则, 将系数为两者之和以及 指数为原指数的新结点放入 PC 链尾, 原两结点也删除, PA首结点指数小: 删除PA首结点,将其放入 PC 链尾。 • PB首结点指数小: 删除PB首结点,将其放入 PC 链尾。 • 注意: 二个多项式的中的多余部分,插入PC 链尾。
2、线性表 • 问题:在考虑成功和失败两种情况下,顺序存储的线形表的平均查找长度? • 问题:原单链表如下图所示。请将所有的链接指针全部颠倒。 next h ∧ { point newh, p; { newh = NULL; while ( h < > NULL ) { p = h; ; p-> next = newh; newh = p; } ; 【 】 h = newh; } } 该语句为 h = p ->next
1.s->prior->next = s->next 2.s->next->prior = s->prior 3.s->prior = h->prior 4.s->next = h 5. h->prior->next =s 6. h->prior = s 2、线性表 问题: :把 L A B C D L B A C D = ( , , , )转化为 = ( , , , ),注意必须先删除数 B A 据场为 的节点,再将其插入到 数据场为 的节点之前,请给出具体的操作 s h -> next; h s 步骤。设 = 除 、 外,不许增加其它的变量。 B 第一步:先删除数据场为 的节点的具体的操作步骤: B A 第二步:将数据场为 的节点插入到数据场为 的节点之前的操作步骤: s h 双链表初态: A B C D