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

realloc函数用法解释

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
posted @ 2025-03-20 19:47  钱塘江畔  阅读(31)  评论(0)    收藏  举报