C语言数据结构(二),基础的线性表,单链表

《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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值