循环链表 C实现

//没有头结点
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
typedef struct List
{
	int  data;
	struct List *next;
}list;

void creat_list(list **p)//如果链表为空,则创建一个链表,指针域指向自己,否则寻找尾节点,将
{						 //将尾节点的指针域指向这个新节点,新节点的指针域指向头结点
	int item;
	list *temp;
	list *target;
	printf("输入节点的值,输入0结束\n");
	while (1)
	{
		scanf("%d", &item);
		if (item == 0)return;

		if (*p == NULL)   //如果输入的链表是空。则创建一个新的节点,使其next指针指向自己  (*head)->next=*head;
		{
			*p = (list *)malloc(sizeof(list));
			if (!*p)exit(0);
			(*p)->data = item;
			(*p)->next = *p;
		}
		else		//输入的链表不是空的,寻找链表的尾节点,使尾节点的next=新节点。新节点的next指向头节点
		{
			for (target = *p; target->next != *p; target = target->next);//寻找尾节点

			temp = (list *)malloc(sizeof(list));
			if (!temp)exit(0);
			temp->data = item;
			temp->next = *p;  //新节点指向头节点
			target->next = temp;//尾节点指向新节点
			//尾插法
		}
	}
}
void insert(list **pNode, int place, int num)  //链表的插入  
{
	list *temp, *target;
	int i;
	if (place == 1)				//如果输入的数字是1,表示要插入头节点。应该特殊处理
	{						//首先找到尾节点,让后让新节点的next指向头节点,尾节点指向新的头节点,在让头指针指向temp。这要特别注意
		temp = (list *)malloc(sizeof(list));
		if (!temp)exit(0);
		temp->data = num;
		for (target = *pNode; target->next != *pNode; target = target->next);

		temp->next = *pNode;//新结点的next指向原先的头节点
		target->next = temp;
		*pNode = temp;/特别注意,头结点换人了
	}

	else			//在其他的地方插入节点。  同样先找到要插入的位置,如果位置超出链表的长度,自动插入队尾。						tar  new  原来是2
	{				//找到要插入位置的前一个节点target,让target->next=temp,插入节点的前驱指向新节点,新节点指向target->next的地址  1    2   3  
		for (i = 1, target = *pNode; target->next != *pNode&&i != place - 1; target = target->next, i++);
		temp = (list *)malloc(sizeof(list));
		temp->data = num;

		temp->next = target->next;
		target->next = temp;
	}

}

void Delete(list **pNode, int place)  //删除操作
{
	list *temp, *target;
	int i;
	temp = *pNode;
	if (temp == NULL)				//首先判断链表是否为空
	{
		printf("这是一个空指针 无法删除\n");
		return;
	}
	if (place == 1)		//如果删除的是头节点	
	{				//应当特殊处理,找到尾节点,使尾节点的next指向头节点的下一个节点 rear->next=(*head)->next;然后让新节点作为头节点,释放原来的头节点
		for (target = *pNode; target->next != *pNode; target = target->next);
		temp = *pNode;

		*pNode = (*pNode)->next;
		target->next = *pNode;
		free(temp);
	}
	else
	{		//删除其他节点
		for (i = 1, target = *pNode; target->next != *pNode&&i != place - 1; target = target->next, i++); //首先找出尾节点
		if (target->next == *pNode)		//判断要删除的位置是否大于链表长度,若大于链表长度,特殊处理直接删除尾节点
		{
			for (target = *pNode; target->next->next != *pNode; target = target->next);//找出尾节的前一个节点
			temp = target->next;												 //	尾节点的前一个节点直接指向头节点  释放原来的尾节点									
			target->next = *pNode;
			printf("数字太大删除尾巴\n");
			free(temp);
		}
		else
		{
			temp = target->next;//  删除普通节点  找到要删除节点的前一个节点target,使target指向要删除节点的下一个节点  转存删除节点地址
			target->next = temp->next;	//  然后释放这个节点
			free(temp);
		}
	}
}

int findval(list *pNode, int val) //寻找值
{
	int i = 1;
	list *node;
	node = pNode;
	while (node->data != val&&node->next != pNode)
	{
		i++;
		node = node->next;
	}
	if (node->next == pNode&&node->data != val)//尾节点指向头节点就跳出,因此还要检测一次为节点的data
	{
		return -1;
	}
	return i;
}



void show(list *p)//遍历,循环链表的遍历最好用do while语句 ,因为头节点就有值
{
	list *temp;
	temp = p;
	do
	{
		printf("%5d", temp->data);
		temp = temp->next;
	} while (temp != p);

	printf("\n");
}
int main()
{
	list *head = NULL;
	list *val = NULL;
	int place, num;
	creat_list(&head);
	printf("原始的链表:");
	show(head);

	printf("输入要删除的位置:");
	scanf("%d", &place);
	Delete(&head, place);
	show(head);

	printf("输入要插入的位置和数据用空格隔开:");
	scanf("%d %d", &place, &num);
	insert(&head, place, num);
	show(head);

	printf("输入你想查找的值:");
	scanf("%d", &num);
	place = findval(head, num);
	if (place != -1)printf("找到的值的位置是place=%d\n", place);
	else printf("没找到值\n");

	system("pause");
	return 0;
}

创建循环链表
在这里插入图片描述
循环链表的插入
在这里插入图片描述
循环链表的删除
在这里插入图片描述
程序运行效果如图:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值