数据结构之循环链表(C语言)

循环链表概念:

       循环链表是一种特殊的链表结构。它与普通链表不同的地方在于,最后一个节点指向第一个节点,形成了一个环。这也就意味着,在循环链表中,每个节点都有前驱节点和后继节点。循环链表既可以向前遍历,也可以向后遍历。循环链表的应用场景主要是在需要循环处理数据的场合,例如游戏中的玩家列表、环形缓存等。

循环单链表的操作

基本代码:

struct Node {
	int data;
	struct Node* next;
};

struct Node* head = NULL;//头指针

int count = 0; //统计节点数量

struct Node* new(int x) //新节点的建立
{
	struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = x;
	temp->next = NULL;
	return temp;
}


1、循环单链表的建立

头插法

void headList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head; //用header来代替头指针来遍历
	if (head == NULL) //链表为空
	{
		head = temp;
		temp->next = head;
		count++;
		return;
	}
	temp->next = head; //新节点指向head
	while (header->next != temp->next) //header移动到最后的节点
		header = header->next;
	header->next = temp; //header指向开头
	head = temp; //头指针更新
	count++;
}

尾插法

void lastList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head;
	if (head == NULL)
	{
		head = temp;
		temp->next = head;
		count++;
		return;
	}
	while (header->next != head) //header移动到尾节点
		header = header->next;
	temp->next = header->next; //新节点指向头指针
	header->next = temp; //header指向新节点
	count++;
} 

2、链表的按位插入

插入时应注意插入位置为开头或结尾,应进行特殊处理。

void Insert(int x, int data)
{
	struct Node* temp = new(data);
	struct Node* header = head;
	if (x == 1) //插入位置为1
	{
		temp->next = head;
		while (header->next != temp->next) //header移动到最后节点
			header = header->next;
		header->next = temp; //header指向新节点
		head = temp; //head更新
		count++;
		return;
	}
	if (x == count) //插入位置为count
	{
		while(header->next != head) //移动到最后节点
			header = header->next;
		temp->next = header->next; //新节点指向开头
		header->next = temp; //header指向新节点
		count++; 
		return; 
	}
	if (x<1 || x>count) //判断插入位置是否非法
	{
		printf("error!");
		return;
	}
	for (int i = 1; i < x-1; i++) //header移动到插入位置前节点
		header = header->next;
	temp->next = header->next; //新节点指向header指向的节点
	header->next = temp; //header指向新节点
	count++;
}

3、按位删除

注意删除节点位置为1时,应特殊处理;

void delete(int x)
{
	struct Node* header = head;
	if (x<1 || x>count) //判断删除位置是否合法
	{
		printf("error!\n");
		return;
	}
	if (head == NULL) //链表为空
	{
		printf("empty!\n");
		return;
	}
	if (x == 1) //删除节点位置为开头
	{
		while (header->next != head) //header移动到最后节点
			header = header->next;
		struct Node* A = head; //保存head节点
		head = head->next; //head移动
		printf("delete a number is %d\n", A->data); //打印
		header->next = head; //将header指向新的head
		free(A); //释放内存
		count--; //数量-1
		return;
	}
	for (int i = 1; i < x - 1; i++) //header移动到删除位置前节点
		header = header->next;
	struct Node* A = header->next; //保存删除节点地址
	header->next = A->next; // header指向删除节点的后节点
	printf("delete a number is %d\n", A->data);
	free(A);
	count--;
}

完整代码:
 

struct Node {
	int data;
	struct Node* next;
};

struct Node* head = NULL;//头指针

int count = 0; //统计节点数量

struct Node* new(int x) //新节点的建立
{
	struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = x;
	temp->next = NULL;
	return temp;
}
//头插法
void headList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head; //用header来代替头指针来遍历
	if (head == NULL)
	{
		head = temp;
		temp->next = head;
		count++;
		return;
	}
	temp->next = head; //新节点指向head
	while (header->next != temp->next) //header移动到最后的节点
		header = header->next;
	header->next = temp; //header指向开头
	head = temp; //头指针更新
	count++;
}
//尾插法
void lastList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head;
	if (head == NULL)
	{
		head = temp;
		temp->next = head;
		count++;
		return;
	}
	while (header->next != head) //header移动到尾节点
		header = header->next;
	temp->next = header->next; //新节点指向头指针
	header->next = temp; //header指向新节点
	count++;
} 

//按位插入
void Insert(int x, int data)
{
	struct Node* temp = new(data);
	struct Node* header = head;
	if (x == 1) //插入位置为1
	{
		temp->next = head;
		while (header->next != temp->next) //header移动到最后节点
			header = header->next;
		header->next = temp; //header指向新节点
		head = temp; //head更新
		count++;
		return;
	}
	if (x == count) //插入位置为count
	{
		while(header->next != head) //移动到最后节点
			header = header->next;
		temp->next = header->next; //新节点指向开头
		header->next = temp; //header指向新节点
		count++; 
		return; 
	}
	if (x<1 || x>count) //判断插入位置是否非法
	{
		printf("error!");
		return;
	}
	for (int i = 1; i < x-1; i++) //header移动到插入位置前节点
		header = header->next;
	temp->next = header->next; //新节点指向header指向的节点
	header->next = temp; //header指向新节点
	count++;
}
//删除
void delete(int x)
{
	struct Node* header = head;
	if (x<1 || x>count) //判断删除位置是否合法
	{
		printf("error!\n");
		return;
	}
	if (head == NULL) //链表为空
	{
		printf("empty!\n");
		return;
	}
	if (x == 1) //删除节点位置为开头
	{
		while (header->next != head) //header移动到最后节点
			header = header->next;
		struct Node* A = head; //保存head节点
		head = head->next; //head移动
		printf("delete a number is %d\n", A->data); //打印
		header->next = head; //将header指向新的head
		free(A); //释放内存
		count--; //数量-1
		return;
	}
	for (int i = 1; i < x - 1; i++) //header移动到删除位置前节点
		header = header->next;
	struct Node* A = header->next; //保存删除节点地址
	header->next = A->next; // header指向删除节点的后节点
	printf("delete a number is %d\n", A->data);
	free(A);
	count--;
}


void Print()
{
	struct Node* header = head;
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", header->data);
		header = header->next;
	}
	printf("\n");
}

int main()
{
	lastList(3);
	lastList(5);
	lastList(2);
	lastList(4);
	Insert(1,8);
	Print();
	delete(1);
	Print();
	return 0;
}

循环双链表的操作

基本代码:

struct Node {
	int data;
	struct Node* left;
	struct Node* right;
};

struct Node* head = NULL;

int count = 0;

struct Node* new(int x)
{
	struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = x;
	temp->left = NULL;
	temp->right = NULL;
	return temp;
}

1、循环双链表的建立

头插法

void headList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head;
	if (head == NULL) //链表为空
	{
		head = temp;
		temp->right = head; //指向新节点
		temp->left = head; //指向新节点
		count++;
		return;
	}
	while (header->right != head) //header指向最后节点
		header = header->right;
	temp->right = head; //新节点右指针指向head
	head->left = temp; //head指向节点的左节点指向新节点
	temp->left = header; //新节点左指针指向header
	header->right = temp; //header右指针指向新节点
	head = temp; //头指针更新
	count++;
}

尾插法

void lastList(int x)
{
	struct Node* header = head;
	struct Node* temp = new(x);
	if (head == NULL)
	{
		head = temp;
		temp->right = head;
		temp->left = temp;
		count++;
		return;
	}
	while (header->right != head) //header指向尾节点
		header = header->right;
	temp->right = header->right; //新节点右指针指向head
	head->left = temp; //head的左指针指向新节点
	header->right = temp; //header的右指针指向新节点
	temp->left = header; //新节点的左指针指向header
	count++;
}

2、按位插入

应对插入位置为1的情况进行特殊处理;


void Insert(int x, int data)
{
	struct Node* header = head;
	struct Node* temp = new(data);
	if (head == NULL) 
	{
		printf("error!/n");
		return;
	}
	if (x<1 || x>count)
	{
		printf("error!\n");
		return;
	}
	if (x == 1) //插入位置为开头
	{
		while (header->right != head) //移动到尾节点
			header = header->right;
		temp->right = head; //新节点的右指针指向头节点
		header->right = temp; //header的右指针指向新节点
		temp->left = header; //新节点的左指针指向尾节点
		head->left = temp; //头节点的左指针指向新节点
		head = temp; //头指针的更新
		count++;
		return;
	}
	for (int i = 1; i <= x - 1; i++)
		header = header->right;
	temp->right = header->right;
	header->right->left = temp;
	header->right = temp;
	temp->left = header;
	count++;
}

3、按位删除

对删除位置为开头和删除位置为结尾的情况进行特殊处理;

void delete(int x)
{
	struct Node* header = head;
	if (x<1 || x>count)
	{
		printf("error!\n");
		return;
	}
	if (x == 1) 
	{
		struct Node* A = head;
		head = head->right;
		head->left = A->left;
		A->left->right = head;
		free(A);
		count--;
		return;
	}
	if (x == count)
	{
		struct Node* A = head->left;
		header = A->left;
		header->right = head;
		head->left = header;
		free(A);
		count--;
		return;
	}
	for (int i = 1; i < x - 1; i++)
		header = header->right;
	struct Node* A = header->right;
	header->right = A->right;
	A->right->left = header;
	free(A);
	count--;
}

4、遍历(打印)

void Print()
{
	int falg = 0;
	struct Node* header = head;
	while (header != head || falg == 0)
	{
		printf("%d ", header->data);
		if (header->right == head)
		{
			falg = 1;
			break;
		}
		header = header->right;
	}
	printf("\n");
	struct Node* last = header;
	while (header != last|| falg == 1)
	{
		printf("%d ", header->data);
		if (header->left == last)
		{
			falg = 0;
			break;
		}
		header = header->left;
	}
	printf("\n");
}

完整代码:

struct Node {
	int data;
	struct Node* left;
	struct Node* right;
};

struct Node* head = NULL;

int count = 0;

struct Node* new(int x)
{
	struct Node* temp = (struct Node*)malloc(sizeof(struct Node));
    temp->data = x;
	temp->left = NULL;
	temp->right = NULL;
	return temp;
}

//头插法
void headList(int x)
{
	struct Node* temp = new(x);
	struct Node* header = head;
	if (head == NULL) //链表为空
	{
		head = temp;
		temp->right = head; //指向新节点
		temp->left = head; //指向新节点
		count++;
		return;
	}
	while (header->right != head) //header指向最后节点
		header = header->right;
	temp->right = head; //新节点右指针指向head
	head->left = temp; //head指向节点的左节点指向新节点
	temp->left = header; //新节点左指针指向header
	header->right = temp; //header右指针指向新节点
	head = temp; //头指针更新
	count++;
}

//尾插法
void lastList(int x)
{
	struct Node* header = head;
	struct Node* temp = new(x);
	if (head == NULL)
	{
		head = temp;
		temp->right = head;
		temp->left = temp;
		count++;
		return;
	}
	while (header->right != head) //header指向尾节点
		header = header->right;
	temp->right = header->right; //新节点右指针指向head
	head->left = temp; //head的左指针指向新节点
	header->right = temp; //header的右指针指向新节点
	temp->left = header; //新节点的左指针指向header
	count++;
}

//按位插入
void Insert(int x, int data)
{
	struct Node* header = head;
	struct Node* temp = new(data);
	if (head == NULL) 
	{
		printf("error!/n");
		return;
	}
	if (x<1 || x>count)
	{
		printf("error!\n");
		return;
	}
	if (x == 1) //插入位置为开头
	{
		while (header->right != head) //移动到尾节点
			header = header->right;
		temp->right = head; //新节点的右指针指向头节点
		header->right = temp; //header的右指针指向新节点
		temp->left = header; //新节点的左指针指向尾节点
		head->left = temp; //头节点的左指针指向新节点
		head = temp; //头指针的更新
		count++;
		return;
	}
	for (int i = 1; i <= x - 1; i++)
		header = header->right;
	temp->right = header->right;
	header->right->left = temp;
	header->right = temp;
	temp->left = header;
	count++;
}
//删除
void delete(int x)
{
	struct Node* header = head;
	if (x<1 || x>count)
	{
		printf("error!\n");
		return;
	}
	if (x == 1) 
	{
		struct Node* A = head;
		head = head->right;
		head->left = A->left;
		A->left->right = head;
		free(A);
		count--;
		return;
	}
	if (x == count)
	{
		struct Node* A = head->left;
		header = A->left;
		header->right = head;
		head->left = header;
		free(A);
		count--;
		return;
	}
	for (int i = 1; i < x - 1; i++)
		header = header->right;
	struct Node* A = header->right;
	header->right = A->right;
	A->right->left = header;
	free(A);
	count--;
}
//打印
void Print()
{
	int falg = 0;
	struct Node* header = head;
	while (header != head || falg == 0)
	{
		printf("%d ", header->data);
		if (header->right == head)
		{
			falg = 1;
			break;
		}
		header = header->right;
	}
	printf("\n");
	struct Node* last = header;
	while (header != last|| falg == 1)
	{
		printf("%d ", header->data);
		if (header->left == last)
		{
			falg = 0;
			break;
		}
		header = header->left;
	}
	printf("\n");
}
int main()
{
	lastList(3);
	lastList(5);
	lastList(8);
	lastList(9);
	lastList(4);
	Print();
	Insert(1, 88);
	Insert(6, 99);
	Print();
	delete(5);
	Print();
	return 0;
}

链表章节完结!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值