C语言实现删除单向不循环链表重复节点

本文介绍了如何使用C语言实现单向不循环链表中删除重复节点的方法,包括仅保留第一个重复节点和完全删除所有重复节点的操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

预置条件

typedef struct link_list {
	int data;
	struct link_list* next;
}LINK_NODE; //定义一个链表节点,包含数据属性data,和指向该结构体的指针netx

1.删除重复节点(只保留第一个重复的节点)

LINK_NODE* del_repetition(LINK_NODE* phead)
{
	/*
	删除链表中的重复元素(重复元素中只保留第一个重复的元素)
	方法:双指针,a指针指向最前面的节点,b指针遍历链表,找出与a指针值相同的节点,删除节点。
	*/

	LINK_NODE* ptmp = phead;
	LINK_NODE* pstart = phead;
	LINK_NODE* pfun = phead;
	LINK_NODE* pre = NULL;
	
	if (NULL == phead) //如果链表为空,则返回空
	{
		printf("warning:链表为空\n");
		return phead;
	}
	
	while (phead != NULL)//外层循环使phead指针依次指向每一个节点
	{
		pfun = phead;
		while (pfun != NULL && pfun->next != NULL)//内层循环使pfun指针依次指向phead之后的每一个节点
		{										  //如果pfun节点的值等于phead的值,则删除该节点,										
			if (pfun->next->data == phead->data)  //并将该节点的上一个节点与该节点的下一个节点连接;
			{
				pre = pfun->next;
				pfun->next = pre->next;
				free(pre);
				pre = NULL;
				continue;		//此时pfun->next已经指向下一个节点了,因此此时pfun不需要偏移
			}
			pfun = pfun->next;
		}
		phead = phead->next;
	}

	return pstart;
}

删除所有重复节点(重复节点一个都不留)

LINK_NODE* del_all(LINK_NODE* phead)
{
	/*
	删除链表中所有相同元素(删除所有)
	方法:	双指针,a指针指向最前面的节点,b指针遍历链表,找出与a指针值相同的节点,删除节点。
			如果有删除的情况,说明后面链表中有与a指针节点值相同的节点,然后判断a节点是不是头节点
			头节点做特殊处理即可。
	*/

	LINK_NODE* pre = NULL;
	LINK_NODE* ptmp = NULL;
	LINK_NODE* pstart = phead;
	LINK_NODE* pp = phead;
	int count = 0;

	if (NULL == phead)//如果链表为空,则返回空
	{
		printf("warning:链表为空\n");
		return phead;
	}

	while (pstart != NULL){  //外层循环使pstart指针依次指向每一个节点
		ptmp = pstart;
		while (ptmp->next != NULL) { //如果链表中有与pstart节点值相同的元素,则删除
			if (ptmp->next->data == pstart->data){
				pre = ptmp->next;
				ptmp->next = ptmp->next->next;
				free(pre);
				pre = NULL;
				count = 1;
				continue;
			}
			ptmp = ptmp->next;
		}
		if (1 == count) {	//如果删除了,判断有重复数值的pstart节点是不是头结点
			if (pstart == phead) {
				phead = phead->next; //是头结点,让phead头节点指针向后偏移,然后删除pstart原头节点
				free(pstart);
				pstart = phead;
				pp = pstart;
			}
			else{
				pp->next = pstart->next; //如果不是头结点,让pstart指向节点的前一个节点的next指向pstart的下一个节点。
				free(pstart);
				pstart = pp->next;
			}
			count = 0;
			continue;
		}
		pp = pstart;
		pstart = pstart->next;
	}

	return phead;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值