删除两个双向循环链表中相同数值节点 -- C语言

83 篇文章 2 订阅
30 篇文章 0 订阅

代码实现

int removeDoubLoopListNodeByData(st_doubNode ** phead, int data){
	if(NULL == phead ){
		printf("%s: param error\n",__func__);
		return PARAM_ERR;
	}		

	if(NULL == phead){
		return SUCCESS;
	}

	st_doubNode * head = *phead;
	st_doubNode * iter = NULL;
	st_doubNode * p = NULL;

	iter = head;
	do {
		/* 相同 */
		if(data == iter->data){
			/* 摘除点 */
			p = iter;
			iter->prev->next = iter->next;
			iter->next->prev = iter->prev;
			/* 下一循环点 */
			iter = iter->next;
			/*首节点,更新头*/
			if(p == head){
				head = iter;
			}
			
			free(p);
			p = NULL;
			continue;
		}
		
		iter = iter->next;
	}while(iter != head);

	*phead = head;
	
	return SUCCESS;
}


int removeDoubLoopListSameNode(st_doubNode** phead1, st_doubNode** phead2){
	if(NULL == phead1 || NULL == phead2){
		printf("%s: param error\n",__func__);
		return PARAM_ERR;
	}	

#define ARRAR_SIZE	100

	st_doubNode * head1 = *phead1;
	st_doubNode * head2 = *phead2;
	st_doubNode * tail1 = NULL, * tail2 = NULL;
	st_doubNode * iter1 = NULL, * iter2 = NULL;

	int samevals[ARRAR_SIZE] = {0};
	int cnt = 0, i = 0, data = 0;

	if(NULL == head1 || NULL == head2){
		return SUCCESS;
	}

	tail1 = getDouLoopListTail(head1);
	tail2 = getDouLoopListTail(head2);

	/*寻找相同节点*/	
	iter1 = head1;	
	/*
	 * 注意, 对于循环链表使用 do...while 结构,这样用 iter !=  head 可以处理的到头尾节点。      
	 */
	do {
		data = iter1->data;	
		iter2 = head2;
		do {
			if(iter2->data == data){
				samevals[cnt++] = data;
			}
			iter2 = iter2->next;
		} while (iter2 != head2);
		iter1 = iter1->next;
	} while (iter1 != head1);

#ifdef DEBUG
	printf("cnt = %d\n", cnt);
	for(i = 0; i < cnt; i++){
		printf("samevals[%d] = %d\n", i, samevals[i]);
	}
#endif

	// TODO: 删除相同数值节点
	for(i = 0; i < cnt; i++) {
		data = samevals[i];
		removeDoubLoopListNodeByData(&head1, data);
		removeDoubLoopListNodeByData(&head2, data);
	}

	*phead1 = head1;
	*phead2 = head2;

#undef ARRAR_SIZE

	return SUCCESS;
}


void testremoveDoubLoopListSameNode(void){

	printf("************  testremoveDoubLoopListSameNode ************ \n");

	st_doubNode * tail = NULL;

	/*初始化input数据*/
	int input1[10] = {9,6,8,3,0,11,28,119,5,7};
	gDoubHead1 = NULL;
	createDoubList(&gDoubHead1, input1, 10);
    dumpDoubList(gDoubHead1);
	tail = getDouListTail(gDoubHead1);
	tail->next = gDoubHead1;
	gDoubHead1->prev = tail;	

	/*初始化input数据*/
	int input2[10] = {0,1,2,3,4,5,6,7,8,9};
	gDoubHead2 = NULL;
	createDoubList(&gDoubHead2, input2, 10);
    dumpDoubList(gDoubHead2);
	tail = getDouListTail(gDoubHead2);
	tail->next = gDoubHead2;
	gDoubHead2->prev = tail;

	removeDoubLoopListSameNode(&gDoubHead1, &gDoubHead2);

	tail = getDouLoopListTail(gDoubHead1);
	tail->next = NULL;
	gDoubHead1->prev = NULL;	

	tail = getDouLoopListTail(gDoubHead2);
	tail->next = NULL;
	gDoubHead2->prev = NULL;	

	dumpDoubList(gDoubHead1);
	dumpDoubListReverse(gDoubHead1);
	dumpDoubList(gDoubHead2);
	dumpDoubListReverse(gDoubHead2);

}

注意,

用 while 的话,用 iter2 != head 的话,头节点处理不了;用 iter2->next !=  head的话,尾节点处理不了

对于循环链表使用 do...while 结构,这样用 iter !=  head 可以处理的到头尾节点。

代码编译

 gcc listMain.c doublist.c -o a.exe -DDEBUG

调试输出

************  testremoveDoubLoopListSameNode ************
========= Dump Double List 0x183e250 ===========
         9  6  8  3  0  11  28  119  5  7
===================================
========= Dump Double List 0x183e390 ===========
         0  1  2  3  4  5  6  7  8  9
===================================
cnt = 7
samevals[0] = 9
samevals[1] = 6
samevals[2] = 8
samevals[3] = 3
samevals[4] = 0
samevals[5] = 5
samevals[6] = 7
========= Dump Double List 0x183e2f0 ===========
         11  28  119
===================================
========= dump DoubList Reverse 0x183e330 ===========
         119  28  11
================================================
========= Dump Double List 0x183e3b0 ===========
         1  2  4
===================================
========= dump DoubList Reverse 0x183e410 ===========
         4  2  1
================================================

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值