双向链表的合并

A 和 b 是两双向链表。其中每一个结点存放一个整数。试编函数,将链表 b 和链表 a 合并,且去除 其中整数值相同的结点,返回合并后的链表首地址。

【做错过的点】

1.在“r = r->next;”后面还加了一句“p = p->next;”,这是致命错误,会导致结果不正确,因为与r比较的不再是第一个p了

2.冗余代码,如下写了两次p和r的赋值语句,可以归并写到一处的

//先将A中p所指剩余结点插入新链表中
	while (p != NULL)
	{
		//用q指向p的下一个结点
		q = p->next;

		//将p与新链表A中的结点比较有无相同值
		while (r != NULL)
		{
			if (r->data == p->data)
			{
				//若相同则删除p所指结点,取链表中下一个值
				free(p);

				p = q;//冗余
				r = A;

				break;
			}
			r = r->next;

		}

		if (r == NULL)//若无相同值
		{
			//将p结点插入到新链表中
			p->next = A->next;
			p->prior = A;
			if (A->next != NULL)
			{
				A->next->prior = p;
			}
			A->next = p;

			p = q;//冗余
			r = A;
		}

	}

【个人理解】

既要把A中原来相同的元素去掉一个,还要在合并时,把与B相同的元素去掉其中一个,即重复元素中只保留一个元素

【完整代码】

#include 
#include 
#include 
typedef  struct DLNode
{
	int data;
	struct  DLNode *prior,*next;
} LNode;

void Print(DLNode *L)///输出函数
{
	DLNode *p;
	p = L;
	while (p != NULL)
	{
		printf("%d ", p->data);
		p = p->next;
	}
}

///建立不带头结点的双向链表及初始化
DLNode *CreatL(int no)
{
	DLNode *L = (DLNode *)malloc(sizeof(DLNode));   //申请第一个结点空间
	L->next = NULL;                  //初始化一个空链表
	L->prior = NULL;

	DLNode *r;
	r = L;                          //r始终指向终端结点,开始时指向首元素
	int x;                         //x为链表数据域中的数据
	FILE *fp;
	char str1[100] = "data";
	char str2[100] = ".txt";
	char str3[100];
	_itoa(no, str3, 10);
	strcat(str1, str3);
	strcat(str1, str2);

	fp = fopen(str1, "r");
	
	if (fp == NULL)
		exit(0);

	//读取首元素
	fscanf(fp, "%d", &x);
	L->data = x;
	

	//读取剩余元素
	while ((fscanf(fp, "%d", &x)) != EOF)
	{

		DLNode *p;
		p = (DLNode *)malloc(sizeof(DLNode));   //申请新的结点
		p->data = x;                     //结点数据域赋值
		p->next = r->next;
		p->prior = r;
		r->next = p;
		r = p;                 //将结点插入到表头L-->|1|-->|2|-->NULL
	}
	fclose(fp);
	r->next = NULL;
	return L;
}

DLNode* Merge(DLNode* A, DLNode* B)
{
	DLNode*r, *t, *p, *q;
	r = A;
	p = r->next;
	r->next = NULL;
	p->prior = NULL;//断开连接,单独取出A的首元素

	t = B;

	//先将A中p所指剩余结点插入新链表中
	while (p != NULL)
	{
		//用q指向p的下一个结点
		q = p->next;

		//将p与新链表A中的结点比较有无相同值
		while (r != NULL)
		{
			if (r->data == p->data)
			{
				//若相同则删除p所指结点,取链表中下一个值
				free(p);
				break;
			}
			r = r->next;
		}

		if (r == NULL)//若无相同值
		{
			//将p结点插入到新链表中
			p->next = A->next;
			p->prior = A;
			if (A->next != NULL)
			{
				A->next->prior = p;
			}
			A->next = p;
		}

		p = q;
		r = A;
	}


	//先将B中t所指剩余结点插入新链表中
	r = A;
	while (t != NULL)
	{
		//用q指向t的下一个结点
		q = t->next;

		//将t与新链表A中的结点比较有无相同值
		while (r != NULL)
		{
			if (r->data == t->data)
			{
				//若相同则删除t所指结点,取链表中下一个值
				free(t);
				break;
			}
			r = r->next;
		}

		if (r == NULL)//若无相同值
		{
			//将p结点插入到新链表中
			t->next = A->next;
			t->prior = A;
			if (A->next != NULL)
			{
				A->next->prior = t;
			}
			A->next = t;
		}

		t = q;
		r = A;
	}

	return A;
}
int main()
{
	DLNode *A;
	DLNode *B;
	DLNode *C;
	A = CreatL(1);//建立链表与初始化
	B = CreatL(2);
	printf("A: ");
	Print(A);
	printf("\n");

	printf("B: ");
	Print(B);
	printf("\n");

	C = Merge(A, B);

	printf("C: ");
	Print(C);

	return 0;
}
/*建立一个名为data1的txt文件,将此文件放在本程序所在文件夹目录下
文件内容:
1
2
3
4
5
5
*/
/*建立一个名为data2的txt文件,将此文件放在本程序所在文件夹目录下
文件内容:
5
6
7
8
9
10
*/

【测试结果】

你可能感兴趣的:(考研真题总结,C考研真题解析)