数据结构示例之带头节点的、单循环链表

以下为“带头节点的、单循环链表”的简单示例:

1. 用c语言实现的版本

#include<stdio.h> /* EOF(=^Z或F6),NULL */
#include<math.h> /* floor(),ceil(),abs() */
#include<stdlib.h> /* 申请和释放内存 */

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0

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

/* 线性表的单链表存储结构 */
struct LNode
{
	ElemType data;
	struct LNode *next;
};

typedef struct LNode *LinkList; /* 另一种定义LinkList的方法 */

/* 构造一个空的、单向循环链表L */
Status InitList_CL(LinkList *L)
{ 
	*L = (LinkList)malloc(sizeof(struct LNode)); /* 产生头结点,并使L指向此头结点 */
	if (!*L) /* 存储分配失败 */
	{
		exit(OVERFLOW);
	}
	(*L)->next = *L; /* 指针域指向头结点 */
	return OK;
}

/* 若L为空表,则返回TRUE,否则返回FALSE */
Status ListEmpty_CL(LinkList L)
{ 
	if (L->next == L) /* 表尾指针所指元素的next值 等于 自身 */
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

/* 返回L中数据元素个数 */
int ListLength_CL(LinkList L)
{ 
	int i = 0;
	LinkList p = L->next; /* p指向头结点 */
	while (p != L) /* 没到表尾 */
	{
		++i;
		p = p->next;
	}
	return i;
}

/* 在L的第i个位置插入元素e */
Status ListInsert_CL(LinkList *L, int i, ElemType e) /* 改变L */
{ 
	LinkList p = (*L)->next, s; /* p指向头结点 */
	int j = 0;

	if (i<1 || (i>ListLength_CL(*L) + 1)) /* 无法在第i个位置插入 */
	{
		return ERROR;
	}

	while (j < (i - 1)) /* 寻找第i-1个结点 */
	{
		p = p->next;
		++j;
	}
	s = (LinkList)malloc(sizeof(struct LNode)); /* 生成新结点 */
	/* 在第i个位置插入L中 */
	s->data = e;
	s->next = p->next;
	p->next = s;

	/* 改变尾结点 */
	if (p == *L) 
	{
		*L = s;
	}

	return OK;
}

/* 当第i个元素存在时,其值赋给e并返回OK,否则返回ERROR */
Status GetElem_CL(LinkList L, int i, ElemType *e)
{
	int j = 1; /* 初始化,j为计数器 */
	LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点

	if ((i < 1) || i > ListLength_CL(L)) /* 第i个元素不存在 */
	{
		return ERROR;
	}

	while (j<i)
	{ /* 顺指针向后查找,直到p指向第i个元素 */
		p = p->next;
		++j;
	}
	*e = p->data; /* 取第i个元素 */

	return OK;
}

/* 在L的第i个位置删除元素 */
Status ListDelete_CL(LinkList *L, int i)
{
	LinkList p = (*L)->next, s; /* 由于L为带表头的、单向循环链表的表尾指针,所以p指向头结点 */
	int j = 0;

	if (i<1 || i>ListLength_CL(*L)) /* 无法删除第i个位置上的元素 */
	{
		return ERROR;
	}

	while (j < (i - 1)) /* 寻找第i-1个结点 */
	{
		p = p->next;
		++j;
	}
	
	/* 删除第i个位置上的元素 */
	s = p->next;
	p->next = s->next;
	/* 改变尾结点 */
	if (s == *L)
	{
		*L = p;
	}
	free(s);

	return OK;
}

/* 依次对L的每个数据元素调用函数vi()。一旦vi()失败,则操作失败 */
Status ListTraverse_CL(LinkList L, void(*vi)(ElemType))
{ 
	LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
	while (p != L->next)
	{
		vi(p->data);
		p = p->next;
	}
	return OK;
}

/* 若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱,否则操作失败,pre_e无定义 */
Status PriorElem_CL(LinkList L, ElemType cur_e, ElemType *pre_e)
{ 
	LinkList q, p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
	q = p->next;
	while (q != L->next) /* p没到表尾 */
	{
		if (q->data == cur_e)
		{
			*pre_e = p->data;
			return TRUE;
		}
		p = q;
		q = q->next;
	}
	return FALSE;
}

/* 若cur_e是L的数据元素,且不是最后一个,则用next_e返回它的后继,否则操作失败,next_e无定义 */
Status NextElem_CL(LinkList L, ElemType cur_e, ElemType *next_e)
{
	LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
	while (p != L) /* p没到表尾 */
	{
		if (p->data == cur_e)
		{
			*next_e = p->next->data;
			return TRUE;
		}
		p = p->next;
	}
	return FALSE;
}

/* 返回L中第1个与e满足关系compare()的数据元素的位序。若这样的数据元素不存在,则返回值为0 */
int LocateElem_CL(LinkList L, ElemType e, Status(*compare)(ElemType, ElemType))
{ 
	int i = 0;
	LinkList p = L->next->next; //由于L为带表头的、单向循环链表的表尾指针,所以p为第一个有效结点
	while (p != L->next)
	{
		++i;
		if (compare(p->data, e)) /* 满足关系 */
			return i;
		p = p->next;
	}
	return 0;
}
// 比较函数
Status compare(ElemType c1, ElemType c2)
{
	if (c1 == c2)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void visit(ElemType c)
{
	printf("%d ", c);
}

/* 销毁线性表L */
Status DestroyList_CL(LinkList *L)
{ 
	LinkList q, p = (*L)->next; /* 由于L为带表头的、单向循环链表的表尾指针,p指向头结点 */
	while (p != *L) /* 没到表尾 */
	{
		q = p->next;
		free(p);
		p = q;
	}
	free(*L);
	*L = NULL;
	return OK;
}

/* 将L重置为空表 */
Status ClearList_CL(LinkList *L)
{ 
	LinkList p, q;
	*L = (*L)->next; /* 由于L为带表头的、单向循环链表的表尾指针,其后继结点为头结点 */
	p = (*L)->next; /* p指向第一个结点 */
	while (p != *L) /* 没到表尾 */
	{
		q = p->next;
		free(p);
		p = q;
	}
	(*L)->next = *L; /* 头结点指针域指向自身 */
	return OK;
}

/* 合并两个单循环链表 */
void MergeList_CL(LinkList *La, LinkList Lb)
{
	LinkList p = Lb->next; //由于Lb为带表头的、单向循环链表的表尾指针,所以p为单循环链表Lb的头节点
	Lb->next = (*La)->next; //将单循环链表Lb的后继 更新为 La的头节点
	(*La)->next = p->next; //将单循环链表la的后继 更新为 Lb的第一个有效节点
	free(p); //释放 单循环链表Lb的头节点
	*La = Lb; //将La的值 更新为 Lb的值,使两者都指向 合并后的 新链表的表尾
}

void main()
{
	LinkList L,Lb;//带头节点的、单向循环链表的表尾指针
	ElemType e;
	int j;
	Status i;

	/* 初始化单循环链表L */
	i = InitList_CL(&L); 
	if (i == OK)
	{
		printf("初始化单循环链表成功.\n");
	}
	else
	{
		printf("初始化单循环链表失败!\n");
		return;
	}

	i = ListEmpty_CL(L);
	if (i == OK)
	{
		printf("单循环链表为空.\n");
	}
	else
	{
		printf("单循环链表非空!\n");
	}

	ListInsert_CL(&L, 1, 3); /* 在L中第1个位置插入3 */
	ListInsert_CL(&L, 2, 5); /* 在L中第2个位置插入5 */
	ListInsert_CL(&L, 3, 7); /* 在L中第2个位置插入5 */

	/* 获取第1个位置的元素 */
	i = GetElem_CL(L, 1, &e);
	if (i == OK)
	{
		printf("L中第%d个元素的值为%d。\n", 1, e);
	}
	else
	{
		printf("未能获取L中第%d个元素,请检查!\n", 1);
		return ;
	}
	j = LocateElem_CL(L, 5, compare);
	if (j)
	{
		printf("元素5的位置为%d\n", j);
	} 
	else 
	{
		printf("元素5不在单循环列表中\n");
	}
	//返回它的前驱
	i = PriorElem_CL(L, 5, &j);
	if (i == OK)
	{
		printf("L中元素%d的前驱为%d。\n", 5, j);
	}
	else
	{
		printf("未能获取L中元素%d的前驱(或者,它已是第一个元素,或该元素本是不存在)!\n", 5);
	}

	//返回它的后继
	i = NextElem_CL(L, 5, &j);
	if (i == OK)
	{
		printf("L中元素%d的后继为%d。\n", 5, j);
	}
	else
	{
		printf("未能获取L中元素%d的后继(或者,它已是最后一个元素,或该元素本是不存在)!\n", 5);
	}

	/* 返回L中数据元素个数 */
	j = ListLength_CL(L);
	printf("L中数据元素个数=%d。\n", j);

	printf("L中的数据元素依次为:");
	ListTraverse_CL(L, visit);

	/* 在L的第1个位置删除元素 */
	j = 3;
	i = ListDelete_CL(&L, j);
	if (i == OK)
	{
		printf("\n单循环链表成功删除第%d个元素.\n", j);
	}
	else
	{
		printf("\n单循环链表删除第%d个元素失败!\n", j);
		return;
	}
	/* 返回L中数据元素个数 */
	j = ListLength_CL(L);
	printf("L中数据元素个数=%d。\n", j);

	printf("L中的数据元素依次为:");
	ListTraverse_CL(L, visit);

	/* 将L重置为空表 */
	i = ClearList_CL(&L);
	if (i == OK)
	{
		printf("\n已经重置单循环链表\n");
	}

	/* 返回L中数据元素个数 */
	j = ListLength_CL(L);
	printf("重置后,L中数据元素个数=%d。\n", j);

	/* 销毁单循环链表 */
	i = DestroyList_CL(&L);
	if (i == OK)
	{
		printf("已经销毁单循环链表,链表尾指针已经置为%0x.\n", L);
	}
	////////////////////////////////////////////////////////
	////测试链表合并
	i = InitList_CL(&L);
	if (i == OK)
	{
		printf("初始化单循环链表成功.\n");
	}
	else
	{
		printf("初始化单循环链表失败!\n");
		return;
	}
	ListInsert_CL(&L, 1, 3); /* 在L中第1个位置插入3 */
	ListInsert_CL(&L, 2, 5); /* 在L中第2个位置插入5 */
	ListInsert_CL(&L, 3, 7); /* 在L中第2个位置插入5 */

	i = InitList_CL(&Lb);
	if (i == OK)
	{
		printf("初始化单循环链表成功.\n");
	}
	else
	{
		printf("初始化单循环链表失败!\n");
		return;
	}
	ListInsert_CL(&Lb, 1, 2); /* 在L中第1个位置插入3 */
	ListInsert_CL(&Lb, 2, 4); /* 在L中第2个位置插入5 */
	ListInsert_CL(&Lb, 3, 6); /* 在L中第2个位置插入5 */

	MergeList_CL(&L, Lb); //合并两个单循环链表
	printf("在合并后的单循环链表中,数据元素依次为:");
	ListTraverse_CL(Lb, visit);
	printf("\n");
}
运行结果如下图所示:



猜你喜欢

转载自blog.csdn.net/chinawangfei/article/details/53000944