《C语言数据结构》严蔚敏,吴伟民版。
上章内容链接:https://blog.csdn.net/daqino1/article/details/88677202
下章内容链接:https://blog.csdn.net/daqino1/article/details/88813280
以下内容为基础的线性表,单链表。
线性表:N个数据元素的有限序列。
// 抽象线性表
ADT List {
// 初始化线性表L
InitList( &L );
// 销毁线性表L
DestroyList( &L );
// 重置L表为空表
ClearList( &L );
// 判断L表是为空表 TRUE,空表;FALSE,非空表
ListEmpty( &L );
// L表中的数据元素个数
ListLength( L );
// 用e返回L表中第i个数据元素的值
GetElem( L, i, &e);
/* 返回L中第1个与e满足关系compare()对数据元素的位序。若这样的数据元素不存在,返回值为0*/
LocateElem( L, e, compare() );
/*若cur_e是L的数据元素,且不是第一个,则用per_e返回它的前驱,否则操作失败,pre_e无定义*/
PriorElem( L, cur_e, &pre_e);
/*若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义*/
NextElem( L, cur_e, &next_e);
// 在L中第i个位置之前插入新的数据元素e,L的长度加1
ListInsert( &L, i, e);
// 删除L中第i个数据元素,并用e返回其值,L的长度减1
ListDelete( &L, i, &e);
// 依次对L的每个数据元素调用函数visit(). 一旦visit()失败,则操作失败
ListTraverse( L, visit() );
} ADT List
A=AUB的算法:算法2.1
void union(List &La, List &Lb) {
// 将所有在线性表Lb中,但不在La中的数据元素插入到La中
// 求线性表的长度
La_len = ListLength(La);
Lb_len = ListLength(Lb);
for (i = 1; i <= Lb_len; i++) {
// 取出Lb中第i个数据元素赋给e
GetElem(Lb, i, e);
if (!LocateElem(La, e, equal)) {
// La中不存在和e相同的数据元素,插入。
ListInsert(La, ++La_len, e);
}
}
}
集合A和B,非递减有序排列到集合C,算法2.2
void MergeList(List La, List Lb, List &Lc) {
// 已知线性表La和Lb中的数据元素按值非递减排序
// 归并La和Lb得到新的线性表Lc,Lc的数据元素也按值非递减排序
InitList(Lc);
i = j = 1;
k = 0;
La_len = ListLength(La);
Lb_len = ListLength(Lb);
// La和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);
}
while (j <= Lb_len) {
GetElem(Lb, j++, bj);
ListInsert(Lc, ++k, bj);
}
}
动态分配一维数组,算法2.3
//--------线性表的动态分配顺序存储结构---------
#define LIST_INIT_SIZE 100 // 线性表存储空间的初始分配值
#define LISTINCREMENT 10 // 线性表存储空间的分配增量
typedef struct {
ElemType * elem;
int length;
int listsize;
} SqList;
Status InitList_Sq(SqList &L) {
// 构造一个空的线性表L
L.elem = (ElemType *)malloc(LIST_INIT_SIZE*sizeof(ElemType));
if (!L.elem) {
// 存储分配失败
exit(OVERFLOW);
}
// 空表长度为0
L.length = 0;
// 初始存储容量
L.listsize = LIST_INIT_SIZE;
return OK;
}
一维数组插入操作:算法2.4
Status ListInsert_Sq(SqList &L, int i, ElemType e) {
// 在顺序线性表L中第i个位置之前插入新的元素e
// i的合法值为 1<=i<=ListLength_Sq(L) + 1;
if (i < 1 || i > L.length + 1) {
// i值不合法
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;
}
// q为插入位置
q = &(L.elem[i-1]);
for (p = &(L.elem[L.length-1]); p >= q; --p) {
// 插入位置及之后的元素右移
*(p+1) = *p;
}
// 插入e
*q = e;
// 表长增1
++L.length;
return OK;
}
一维数组删除操作:2.5
Status ListDelete_Sq(SqList &L, int i, ElemType &e) {
// 在顺序线性表L中删除第i个元素,并用e返回其值
// i的合法值为 1<=i<=ListLength_Sq(L) + 1;
if (i < 1 || i > L.length + 1) {
// i值不合法
return ERROR;
}
// p为被删除元素的位置
p = &(L.elem[i-1]);
// 被删除元素的值赋给e
e = *p;
// 表尾元素的位置
q = L.elem + L.length - 1;
for (++p; p <= q; ++p) {
// 被删除元素之后的元素左移
*(p-1) = *p
}
// 表长减1
--L.length;
return OK;
}
元素之间的比较函数:算法2.6
int LocateElem_Sq(SqList L, ElemType e, Status (*compare)(ElemType, ElemType)) {
// 在顺序线性表L中查找第1个值与e满足compare()的元素的位序
// 若找到,则返回其在L中的位序,否则返回0
// i的初值为第1个元素的位序
i = 1;
// p的初值为第1个元素的存储位置
p = L.elem;
while (i <= L.length && !(*compare)(*p++, e)) {
++i;
}
if (i <= L.length) {
return i;
} else {
return 0;
}
}
顺序表合并算法:算法2.7
void MergeList_Sq(SqList La, SqList Lb, SqList &Lc) {
// 已知顺序线性表La和Lb的元素按值非递减排序
// 归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列
pa = La.elem;
pb = Lb.elem;
Lc.listsize = Lc.length = La.length + Lb.length;
pc = Lc.elem = (ElemType*)malloc(Lc.listsize * sizeof(ElemType));
if (!Lc.elem) {
// 存储分配失败
exit(OVERFLOW);
}
pa_last = La.elem + La.length - 1;
pb_last = Lb.elem + Lb.length - 1;
while (pa <= pa_last && pb <= pb_last) {
// 归并
if (*pa <= *pb) {
*pc++ = *pa++;
} else {
*pc++ = *pb++;
}
}
while (pa <= pa_last) {
// 插入La的剩余元素
*pc++ = *pa++;
}
while (pb < pb_last) {
// 插入Lb的剩余元素
*pc++ = *pb++;
}
}
线性链表:用一组任意的存储单元存储线性表的数据元素,这个存储单元可以是连续的,也可以不是连续的。
线性表的结点(Node) : 除了存储本身信息外,还需要存储一个指示其后继的信息(即直接后继的存储位置)。结点包括两个域,一个是存储数据元素信息的域,称为数据域;另一个是存储直接后继存储位置的域,称为指针域。
指针或链:指针域中存储的信息。
n个节点链结成一个链表,即为线性表的链式存储结构。链表中的每个结点中,只包含一个指针域,又称为线性链表或者单链表。
头结点:单链表的第一个结点之前附设一个结点。头结点的指针域存储指向第一个结点的指针(即第一个元素结点的存储位置)。
头结点的数据域可以不存储任何信息,也可以存储如线性表的长度等附加信息。
获取单链表第i个元素:算法2.8
//---------------------------线性表的单链表存储结构-----------------------------------
typedef struct Lnode {
ElemType data;
struct Lnode * next;
} LNode, *LinkList;
Status GetElem_L(LinkList L, int i, ElemType &e) {
// L为带头结点的单链表的头指针
// 当第i个元素存在时,其复制给e,并返回OK,否则返回ERROR
p = L->next;
j = 1;
while (p && j < i) {
p = p->next;
++j;
}
if (!p || j > i) {
return ERROR;
}
e = p->data;
return OK;
}
单链表的插入和删除操作: 算法2.9和算法2.10
Status ListInsert_L(LinkList &L, int i, ElemType e) {
// 带头结点的单链线性表L中第i个位置之前插入元素e
p = L;
j = 0;
// 寻找第i-1个节点
while (p && j < i - 1) {
p = p->next;
++j;
}
if (!p || j > i-1) {
// i 小于 1 或者 大于表长
return ERROR;
}
// 生成新节点
s = (LinkList)malloc(sizeof(LNode));
// 插入L中
s->data = e;
s->next = p->next;
p->next = s;
return OK;
}
Status ListDelete_L(LinkList &L, int i, ElemType &e) {
// 在带头结点的单链线性表L中,删除第i个元素,并有e返回其值
p = L;
j = 0;
// 寻找第i个结点,并令p指向其前趋
while (p->next && j < i - 1) {
p = p->next;
++j;
}
if (!(p->next) || j > i-1) {
// 删除位置不合理
return ERROR;
}
// 删除并释放结点
q = p->next;
p->next = q->next;
e = q->data;
free(q);
return OK;
}
建立新的单链表: 算法2.11
void 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;
}
}
合并有序链表:算法2.12
void MergeList_L(LinkList &La, LinkList &Lb, LinkList &Lc) {
// 已知单链线性表La和Lb的元素按值非递减排序
// 归并La和Lb得到新的单链线性表Lc,Lc的元素也按值非递减排列
pa = La->next;
pb = Lb->next;
// 用La的头结点作为Lc的头结点
Lc = pc = 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;
// 释放Lb的头结点
free(Lb);
}
上章内容链接:https://blog.csdn.net/daqino1/article/details/88677202
下章内容链接:https://blog.csdn.net/daqino1/article/details/88813280