具有实用意义的线性链表插入元素和合并(第二章 P39 算法2.20,2.21)

具有实用意义的线性链表插入元素-----算法2.20

具有实用意义的线性链表的合并-----算法2.21

typedef int Status; /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */
typedef int ElemType;

#include<malloc.h> /* malloc()等 */
#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<process.h> /* exit() */

/* 函数结果状态代码 */
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
//#define OVERFLOW -2 


/* -----------------------      带头结点的线性链表类型存储结构    ------------------------*/


typedef struct LNode /* 结点类型 */
{
	ElemType data;
	struct LNode *next;
}LNode, *Link, *Position;

typedef struct LinkList /* 链表类型 */
{
	Link head, tail; /* 分别指向线性链表中的头结点和最后一个结点 */
	int len; /* 指示线性链表中数据元素的个数 */
}LinkList;


/* ---------------------------------------------------------------------------*/

int comp(ElemType c1, ElemType c2)
{
	return c1 - c2;
}

void visit(ElemType c)
{
	printf("%d ", c); /* 整型 */
}


/* ---------------------------------   需要用到的 具有实用意义的线性链表的操作 -----------------------------------*/


Status MakeNode(Link *p, ElemType e)
{ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */
	*p = (Link)malloc(sizeof(LNode));
	if (!*p)
		return ERROR;
	(*p)->data = e;
	return OK;
}

void FreeNode(Link *p)
{ /* 释放p所指结点 */
	free(*p);
	*p = NULL;
}

Status InitList(LinkList *L)
{ /* 构造一个空的线性链表 */
	Link p;
	p = (Link)malloc(sizeof(LNode)); /* 生成头结点 */
	if (p)
	{
		p->next = NULL;
		(*L).head = (*L).tail = p;
		(*L).len = 0;
		return OK;
	}
	else
		return ERROR;
}

Status ClearList(LinkList *L)
{ /* 将线性链表L重置为空表,并释放原链表的结点空间 */
	Link p, q;
	if ((*L).head != (*L).tail)/* 不是空表 */
	{
		p = q = (*L).head->next;
		(*L).head->next = NULL;
		while (p != (*L).tail)
		{
			p = q->next;
			free(q);
			q = p;
		}
		free(q);
		(*L).tail = (*L).head;
		(*L).len = 0;
	}
	return OK;
}

Status DestroyList(LinkList *L)
{ /* 销毁线性链表L,L不再存在 */
	ClearList(L); /* 清空链表 */
	FreeNode(&(*L).head);
	(*L).tail = NULL;
	(*L).len = 0;
	return OK;
}

Status InsFirst(LinkList *L, Link h, Link s) /* 形参增加L,因为需修改L */
{ /* h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前 */
	s->next = h->next;
	h->next = s;
	if (h == (*L).tail) /* h指向尾结点 */
		(*L).tail = h->next; /* 修改尾指针 */
	(*L).len++;
	return OK;
}

Status DelFirst(LinkList *L, Link h, Link *q) /* 形参增加L,因为需修改L */
{ /* h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。 */
  /* 若链表为空(h指向尾结点),q=NULL,返回FALSE */
	*q = h->next;
	if (*q) /* 链表非空 */
	{
		h->next = (*q)->next;
		if (!h->next) /* 删除尾结点 */
			(*L).tail = h; /* 修改尾指针 */
		(*L).len--;
		return OK;
	}
	else
		return FALSE; /* 链表空 */
}

Status Append(LinkList *L, Link s)
{ /* 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的 */
  /* 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新 */
  /* 的尾结点 */
	int i = 1;
	(*L).tail->next = s;
	while (s->next)
	{
		s = s->next;
		i++;
	}
	(*L).tail = s;
	(*L).len += i;
	return OK;
}

ElemType GetCurElem(Link p)
{ /* 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值 */
	return p->data;
}

Status ListEmpty(LinkList L)
{ /* 若线性链表L为空表,则返回TRUE,否则返回FALSE */
	if (L.len)
		return FALSE;
	else
		return TRUE;
}

Position GetHead(LinkList L)
{ /* 返回线性链表L中头结点的位置 */
	return L.head;
}

Position NextPos(Link p)
{ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置 */
  /* 若无后继,则返回NULL */
	return p->next;
}

Status LocatePos(LinkList L, int i, Link *p)
{ /* 返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR */
  /* i=0为头结点 */
	int j;
	if (i<0 || i>L.len)
		return ERROR;
	else
	{
		*p = L.head;
		for (j = 1; j <= i; j++)
			*p = (*p)->next;
		return OK;
	}
}

Status ListTraverse(LinkList L, void(*visit)(ElemType))
{ /* 依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败 */
	Link p = L.head->next;
	int j;
	for (j = 1; j <= L.len; j++)
	{
		visit(p->data);
		p = p->next;
	}
	printf("\n");
	return OK;
}


/* ----------------------------------------------------------------------------------------------------------------*/

Status ListInsert_L(LinkList *L, int i, ElemType e) /* 算法2.20 */
{ /* 在带头结点的单链线性表L的第i个元素之前插入元素e */
	Link h, s;
	if (!LocatePos(*L, i - 1, &h))
		return ERROR; /* i值不合法 */
	if (!MakeNode(&s, e))
		return ERROR; /* 结点分配失败 */
	InsFirst(L, h, s); /*对于从第i个结点开始的链表,第i-1个结点是它的头结点 */
	return OK;
}

Status MergeList_L(LinkList La, LinkList Lb, LinkList *Lc, int(*compare)(ElemType, ElemType))
{ /* 已知单链线性表La和Lb的元素按值非递减排列。归并La和Lb得到新的单链 */
  /* 线性表Lc,Lc的元素也按值非递减排列。(不改变La、Lb)算法2.21 */
	Link ha, hb, pa, pb, q;
	ElemType a, b;
	if (!InitList(Lc))
		return ERROR; /* 存储空间分配失败 */
	ha = GetHead(La); /* ha和hb分别指向La和Lb的头结点 */
	hb = GetHead(Lb);
	pa = NextPos(ha); /* pa和pb分别指向La和Lb的第一个结点 */
	pb = NextPos(hb);
	while (!ListEmpty(La) && !ListEmpty(Lb)) /* La和Lb均非空 */
	{
		a = GetCurElem(pa); /* a和b为两表中当前比较元素 */
		b = GetCurElem(pb);
		if (compare(a, b) <= 0)
		{
			DelFirst(&La, ha, &q);
			InsFirst(Lc, (*Lc).tail, q);
			pa = NextPos(ha);
		}
		else /* a>b */
		{
			DelFirst(&Lb, hb, &q);
			InsFirst(Lc, (*Lc).tail, q);
			pb = NextPos(hb);
		}
	}
	if (!ListEmpty(La))
		Append(Lc, pa);
	else
		Append(Lc, pb);
	FreeNode(&ha);
	FreeNode(&hb);
	return OK;
}



void main()
{
	LinkList La, Lb, Lc;
	int j;
	InitList(&La);
	for (j = 1; j <= 5; j++)
		ListInsert_L(&La, j, j); /* 顺序插入 1 2 3 4 5 */
	printf("La=");
	ListTraverse(La, visit);
	InitList(&Lb);
	for (j = 1; j <= 5; j++)
		ListInsert_L(&Lb, j, 2 * j); /* 顺序插入 2 4 6 8 10 */
	printf("Lb=");
	ListTraverse(Lb, visit);
	InitList(&Lc);
	MergeList_L(La, Lb, &Lc, comp); /* 归并La和Lb,产生Lc */
	printf("Lc=");
	ListTraverse(Lc, visit);
	DestroyList(&Lc);
}

运行结果:

发布了135 篇原创文章 · 获赞 64 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_42185999/article/details/104951090