2022112701 - 线性表笔记
1.线性表的类型定义
抽象数据类型 - 线性表
1.1定义
ADT List {
数据对象:D = {a(i) | a(i) ∈ ElemSet, i = 1,2,...,n, n≥0}
数据关系:R1 = {<a(i-1), a(i)> | a(i=1), a(i) ∈ D, i=2,...,n}
基本操作:
InitList(&L)
操作结果:构造一个空的线性表。
DestoryList(&L)
初始条件:线性表L已存在。
操作结果:销毁线性表L。
ClearList(&L)
初始条件:线性表L已存在。
操作结果:将L重置为空表。
ListEmpty(L)
初始条件:线性表L已存在。
操作结果:若L为空表,则返回TRUE,否则返回FALSE。
ListLength(L)
初始条件:线性表L已存在。
操作结果:返回L中数据元素个数。
GetElem(L, i, &e)
初始条件:线性表L已存在,1≤i≤ListLength(L)。
操作结果:用e返回L中第i个数据元素的值。
LocateElem(L, e, compare())
初始条件:线性表L已存在,compare()是数据元素判定函数。
操作结果:返回L中第1个与e满足关系compare()的数据元素的位序。若这样的元素不存在,
则返回0。
PriorElem(L, cur_e, &pre_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失
败,pre_e无定义。
NextElem(L, cur_e, &next_e)
初始条件:线性表L已存在。
操作结果:若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操
作失败,next_e无定义。
ListInsert(&L, i, e)
初始条件:线性表L已存在,1≤i≤ListLength(L)+1
操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1。
ListDelete(&L, i, &e)
初始条件:线性表L已存在且非空,1≤i≤ListLength(L)。
操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1。
ListTraverse(L, visit())
初始条件:线性表L已存在。
操作结果:依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败。
} ADT List
1.2例1:ListA union ListB
void union(List &La, List Lb) {
// 将所有在Lb中但不在La中的元素插入La
La_len = ListLength(La);
Lb_len = ListLength(Lb);
for (i = 1; i ≤ Lb_len; i++) {
GetElem(Lb, i, e);
if (!LocateElem(La, e, equal)) ListInsert(La, ++La_len, e); // 不存在时尾部插入
}
} union
时间复杂度为O(ListLength(La) x ListLength(Lb))
1.3例2:ListA和ListB非递减有序排列,合并为ListC仍按非递减有序排列
void merge(List La, List Lb, List &Lc) {
// 分别取La和Lb的第i,j个元素,进行比较,a(i)<=b(j)则Lc插入a(i),否则插入b(j)
i,j,k = 1;
InitList(&Lc);
La_len = ListLength(La);
Lb_len = ListLength(Lb);
while (i <= ListLength(La) && j <= ListLength(Lb)) {
GetElem(La, i++, a);
GetElem(Lb, j++, b);
ListInsert(Lc, k++, a <= b ? a : b);
}
while(i <= ListLength(La)) {
GetElem(La, i++, a);
ListInsert(Lc, k++, a);
}
while(j <= ListLength(L)b) {
GetElem(Lb, i++, b);
ListInsert(Lc, k++, b);
}
} merge
时间复杂度为O(ListLength(La) + ListLength(Lb))
2.线性表的顺序表示和实现
LOC(a(i+1)) = LOC(a(i)) + l
LOC(a(i)) = LOC(a1) + (i-1)xl
顺序结构或顺序映像sequential mapping
// 线性表的动态分配顺序存储结构
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配量
#define LISTINCREMENT 10 // 线性表存储空间的分配增量
typedef struct {
ElemType * elem; // 存储空间基址
int length; // 当前长度
int listsize; // 当前分配的存储容量(以sizeof(ElemType)为单位)
}SqList
Status InitList_Sq (SqList &L) {
// 构造一个空的线性表
L.elem = (ElemType *) malloc (LIST_INIT_SIZE * sizeof(ElemType));
if (!L.elem) exit(OVERFLOW); // 存储分配失败
L.length = 0; // 空表长度为0
L.listsize = LIST_INIT_SIZE; // 初始存储容量
returm OK;
} // InitList_Sq
2.1 ListInsert
Status ListInsert_Sq (&L, i, e) {
// 线性表在位置i插入元素e
// i的范围限制,超出范围返回错误
La_len = ListLength(L);
if (i < 1 || i > La_len + 1) return ERROR;
// 存储空间已满,扩容
if (La_len + 1 > L.listsize) {
newbase = (ElemType *)realloc(L.elem, (L.listsize + LISTINCREMENT)*sizeof(ElemType));
if(!newbase) exit(OVERFLOW); // 存储分配失败
L.elem = newbase; // 新基址
L.listsize += LISTINCREMENT; // 增加存储容量
}
// i的位置插入,i+1之后的元素往后移一位
for ( j = La_len + 1 ; i < j ; j--) L[j] = L[j-1];
L(i) = e;
++L.length;
return OK;
} // ListInsert_Sq
2.2 ListDelete
Status ListDelete_Sq (SqList &L, int i, ElemType &e) {
// 在顺序线性表L中删除第i个元素,并用e返回其值
// i的范围是否合法
if ( i < 1 || i > ListLength(L)) return ERROR;
for( j = i ; j < L.length ; j++) L(j) = L(j+1); // 后继元素前移1位
--L.length; // 表长减1
} // ListDelete_Sq
3.线性表的链式表示和实现
结点:数据域,指针域
3.1 线性链表
3.1.1 GetElem
Status GetElem_L (LinkList L, int i, ElemType &e) {
// L为带头结点的单链表的头指针
// 当第i个元素存在时,将其值赋给e并返回OK,否则返回ERROR
p = L -> next; j = 1; // 初始化,p指向第一个结点,j为计数器
while (p && j < i) {
p = p -> next; ++j;
}
if (!p || j > i) return ERROR; // 第i个元素不存在
e = p -> data;
return OK;
} // GetElem_L
3.1.2 ListInsert
Status ListInsert_L (LinkList &L, int i, ElemType &e) {
// 在带头结点的单链线性表L中第i个位置之前插入元素e
p = L; j = 0;
while (p && j < i-1) {
p = p -> next; ++j;
} // 寻找第i-1个节点
if (!p || j > i-1) return ERROR; // 第i-1个元素不存在
s = (LinkList)malloc(sizeof(LNode)); // 生成新节点
s -> data = e;
s -> next = p -> next; p -> next = s; // 插入到L中
return OK;
} // ListInsert_L
3.1.3 ListDelete
Status ListDelete_L (LinkList &L, int i, ElemType &e) {
// 在带头结点的单链线性表L中的,删除第i个元素,并由e返回其值
p = L; j = 0;
while (p -> next && j < i-1) { // 寻找第i个节点,并用p指向其前驱
p = p -> next; ++j;
}
if (!(p -> next) || j > i-1) return ERROR; // 第i个节点不存在
q = p -> next; p -> next = q -> next; // 删除第i个节点
e = q -> data; free(q); // 释放节点
return OK;
} // ListDelte_L
3.1.4 CreateList
Status CreateList_L (LinkList &L, int n) {
// 逆位序输入n个元素的值,建立带头结点的单链线性表L
L = (LinkList)malloc(sizeof(LNode));
L -> next = NULL; // 先建立一个带头结点的单链表
for (i = n; i > 0; --i) {
p = (LinkList) malloc (sizeof(LNode)); // 生成新节点
scanf(&p -> data); // 输入元素值
p -> next = L -> next; L -> next = p; // 插入新节点到表头
}
} // CreateList_L
3.1.5 MergeList
Status MergeList_L (LinkList &La, LinkList &Lb, LinkList &Lc) {
// 已知单链线性表La和Lb的元素按值非递减排列
// 归并La和Lb得到新的单链线性表Lc, Lc的元素也按值非递减排列
pa = La -> next ; pb = Lb -> next; // La和Lb的第一个结点
Lc = pc = La; // 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); // 释放Lb的头结点
return OK;
}
} // MergeList_L
静态链表
3.2 循环链表
3.3 双向链表
带头结点的线性链表类型定义如下:
typedef struct LNode { // 结点类型
ElemType data;
struct LNode *next;
} *Link, *Position;
typedef struct { // 链表类型
Link head, tail; // 分别指向线性链表中的头结点和最后一个节点
int len; // 指示线性链表中数据元素的个数
} LinkList;
Status makeNode (Link &p, ElemType e) ; // 分配由p指向的值为e的节点,并返回OK;分配失败,返回ERROR
void freeNode (Link &p) ; // 释放p指向的节点
Status initList (LinkList &L) ; // 构造一个空的线性链表L
Status destroyList (LinkList &L) ; // 销毁线性链表L,L不再存在
Status clearList (LinkList &L) ; // 将线性链表L重置为空表,并释放原链表的节点空间
Status insFirst (Link h, Link s); // 已知h指向线性链表的头结点,删除链表中的第一个结点并以q返回
Status append (LinkList &L, Link s); // 将指针s所指(彼此以指针相链)的一串节点接在线性链表L的最后一个节点之后,并改变链表L的尾指针指向新的尾结点
Status remove (LinkList &L, Link &q) ; // 删除链表L中尾结点并以q返回,该表链表L的尾指针指向新的尾结点
Status insBefore (LinkList &L, Link &p, Link s); // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,并修改指针p指向新插入的结点
Status insAfter (LinkList &L, Link &p, Link s); // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,并修改指针p指向新插入的结点
Status setCurElem (Link &p, ElemType e); // 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
ElemType getCurElem (Link p); // 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
Status listEmpty (LinkList L); // 若线性链表L为空表,则返回TRUE,否则返回FALSE
int listLength(LinkList L); // 返回线性链表L中元素的个数
Position getHead (LinkList L); // 返回线性链表L中头结点的位置
Position getLast (LinkList L); // 返回线性链表L中最后一个结点的位置
Position priorPos (LinkList L, Link p); // 已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,若无前驱,则返回NULL
Position nextPos (LinkList L, Link p); // 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置,若无后继,则返回NULL
Status locatePos (LinkList L, int i, Link &p); // 返回p指示线性链表L中第i个结点的位置并返回OK,i值不合法时返回ERROR
Position locateElem (LinkList L, ElemType e, Status(*compare)(ElemType, ElemType));
// 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,若不存在,返回NULL
Status ListTraverse(LinkList L, Status(*visit)()); // 依次对L的每个元素调用函数visit()。一旦visit()失败,则操作失败
Status listInsert_L (LinkList &L, int i, ElemType e) {
// 在带头结点的单链线性表L的第i个元素之前插入元素e
if (!locatePos(L, i-1, h)) return ERROR; // i值不合法
if (!makeNode(s, e)) return ERROR; // 结点存储分配失败
insFirst(h, s); // 对于从第i个结点开始的链表,第i-1个结点是它的头结点
return OK;
} // listInsert_L
4. 一元多项式的表示及相加
抽象数据类型一元多项式
ADT Polynomial {
数据对象:D = {a(i) | a(i) ∈ TermSet, i=1,2,3...m, m≥0
TermSet中的每个元素包含一个表示系数的实数和表示指数的整数}
数据关系:R1 = {<a(i-1), a(i)> | a(i-1),a(i) ∈ D, 且a(i-1)中的指数值<a(i)中的指数值, i=1,2,3...n }
基本操作:
createPolyn(&P, m)
操作结果:输入m项的系数和指数,建立一元多项式P。
destroyPolyn(&P)
初始条件:一元多项式P已存在。
操作结果:销毁一元多项式P。
printPolyn(P)
初始条件:一元多项式P已存在。
操作结果:打印输出一元多项式P。
polynLength(P)
初始条件:一元多项式P已存在。
操作结果:返回一元多项式P中的项数。
addPolyn(&Pa, &Pb)
初始条件:一元多项式Pa和Pb已存在。
操作结果:完成多项式相加运算,即:Pa=Pa+Pb,并销毁一元多项式Pb。
subtractPolyn(&Pa, &Pb)
初始条件:一元多项式Pa和Pb已存在。
操作结果:完成多项式相减运算,即Pa = Pa - Pb, 并销毁Pb
multiplyPolyn(&Pa, &Pb)
初始条件:一元多项式Pa和Pb已存在。
操作结果:完成多项式相乘运算,即Pa=PaxPb,并销毁Pb
} ADT Polynomial

浙公网安备 33010602011771号