数据结构一一循环链表

前言

循环链表是另一种形式的链式存储结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。

单循环链表

单循环链表——在单链表中,将终端结点的指针域NULL改为指向表头结点或开始结点即可。如下图(a)所示:
在这里插入图片描述
注意:

循环链表的操作和线性链表基本一样,差别仅在于算法中的循环条件不是p或p->next是否为空,而是它们是否等于头指针(head)。如下图(b)所示:

在这里插入图片描述
单链表的问题:如果不从头结点出发,就无法访问全部结点。
解决方法:只需要将单链表中的终端结点的指针由空指针改为指向头结点

单循环链表的代码实现:

single_list.c

#include <stdio.h>
#include <stdbool.h> //c99才支持bool类型

struct single_list 
{
	struct single_list *next;
	int val;
};

struct single_list_head 
{
	struct single_list *head;
};

//判断循环链表是否为空
bool is_empty(struct single_list_head *head)
{
	return head->head == NULL;
}

//遍历单链表
void dump(struct single_list_head *head)
{
	struct single_list *tmp = head->head;
	int idx = 0;

	while (tmp) 
	{
		printf("[%02d]: %08d\n", idx++, tmp->val);
		tmp = tmp->next;
	}
}

//插入
void insert(struct single_list **prev, struct single_list *elem)
{
	if (!prev)
		return;

	elem->next = *prev;
	*prev = elem;
}

//插入头结点
void insert_head(struct single_list_head *head, struct single_list *elem)
{
	insert(&head->head, elem);
}

//删除
struct single_list* del(struct single_list **prev)
{
	struct single_list *tmp;

	if (!prev)
		return NULL;
	if (*prev == NULL)
		return NULL;
	tmp = *prev; // 要删除的结点
	*prev = (*prev)->next; // 记录待删除结点的下一个结点
	tmp->next = NULL;

	return tmp;
};

//删除头节点
struct single_list* delete_head(struct single_list_head* head)
{
	return del(&head->head);
};

//返回结点所在位置
struct single_list** search(struct single_list_head* head, int target)
{
	struct single_list **prev, *tmp;

	for (prev = &head->head, tmp = *prev;
	     tmp && (tmp->val < target);
	     prev = &tmp->next, tmp = *prev)
		;

	return prev;
};

//倒序
void reverse(struct single_list_head* head)
{
	struct single_list_head tmp = {NULL};
	struct single_list *elem;

	while (!is_empty(head)) 
	{
		elem = delete_head(head);
		insert_head(&tmp, elem);
	}

	head->head = tmp.head;
}

//判断链表是否形成一个环
bool is_cyclic(struct single_list_head* head)
{
	struct single_list *s1, *s2;

	s1 = s2 = head->head;

	while(s1 && s2) 
	{
		s1 = s1->next;
		s2 = s2->next ? s2->next->next:s2->next;

		if (s1 == s2)
			return true;
	}
	return false;
}

//取元素中间值
struct single_list* middle(struct single_list_head* head)
{
	struct single_list *s1, *s2;
	struct single_list pseudo_head;

	pseudo_head.next = head->head;
	s1 = s2 = &pseudo_head;

	while (true) {
		if (!s2 || !s2->next)
			return s1;
		s1 = s1->next;
		s2 = s2->next->next;
	}

	return NULL;
};

int main(int argc, char **argv)
{
	struct single_list_head head = {NULL};
	struct single_list lists[10];
	struct single_list **prev;
	int idx;

	for (idx = 0; idx < 10; idx++) 
	{
		lists[idx].val = idx;
		lists[idx].next = NULL;
	}
    //新插入的结点作为第一个结点
	insert_head(&head, &lists[6]);
	insert_head(&head, &lists[5]);
	insert_head(&head, &lists[4]);
	insert_head(&head, &lists[1]);
	insert_head(&head, &lists[0]);

	printf("=== insert 0, 1, 4, 5, 6\n");
	dump(&head);

	prev = search(&head, 2);
	insert(prev, &lists[2]);
	printf("=== insert 2\n");
	dump(&head);

	printf("middle elem is %d\n", middle(&head)->val);

	prev = search(&head, 2);
	if ((*prev) && ((*prev)->val == 2))
		printf("The list contains %d\n",(*prev)->val);
	else
		printf("The list not contains %d\n",(*prev)->val);

	del(prev); //删除
	prev = search(&head, 2);
	printf("After remove 2\n");
	if ((*prev) && ((*prev)->val == 2))
		printf("The list contains %d\n",(*prev)->val);
	else
		printf("The list not contains %d\n",(*prev)->val);
	dump(&head);

	printf("After reverse \n");
	reverse(&head);
	dump(&head);

	printf("middle elem is %d\n", middle(&head)->val);

	lists[0].next = &lists[6];
	printf("list is%s cyclic\n", is_cyclic(&head)?"":" not");//判断是否有环

	return 0;
}

输出结果:
在这里插入图片描述

发布了71 篇原创文章 · 获赞 42 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/chen1415886044/article/details/103499509