C语言归并两个递增单链表

题目

在这里插入图片描述

解答
#include<stdio.h>
#include<stdlib.h>

typedef struct LNode{
	int data;
	struct LNode *next;
}LNode,*LinkList; //指向单链表结点的指针 

/*初始化单链表L*/
int InitList_L(LinkList *L){
	(*L) = (LinkList)malloc(sizeof(LNode));
	if(!(*L))
		exit(0);
	(*L)->next = NULL;  //将首元结点置为空
	return 1;
}

/*在单链表L第i个位置之前插入e*/
int ListInsert_L(LinkList L, int i, int e){
	LinkList p, s;
	int j;
	
	p = L;
	j = 0; 
	
	while(p && j<i-1){  //寻找第i-1个结点 
		p = p->next;
		++j;
	}
	
	if(!p || j>i-1)
		return 0;

	s = (LinkList)malloc(sizeof(LNode));
	if(!s)
		exit(0);
	s->data = e;
	s->next = p->next;
	p->next = s;

	return 1;
}

/*归并两个递增单链表为一个递增单链表*/
int Algo_1(LinkList La, LinkList *Lb, LinkList *Lc){
	LinkList pa, pb, qa, qb, s;

	/*La或Lb有一个不存在或两个均为空表时,合并错误*/
	if(!La || !Lb || (!La->next && !(*Lb)->next))
		return 0;
	
	*Lc = La;	//利用La的头结点作Lc的头结点
	pa = La; //令pa指向La的头结点【作为新链表的尾结点指针使用】
	qa = La->next; //令qa指向La的首元结点
	qb = (*Lb)->next; //令qb指向Lb的首元结点
	
	/*采尾插法建立递增链表*/
	/*谁小谁先插-->到最后大的在后面,小的在前面*/
	while(qa && qb){ //当La和Lb都未遍历完时
		if(qa->data<=qb->data){ //如果La中结点小,则La中结点插入
			pa->next = qa;  //将qa接到尾结点后面
			pa = qa;  //尾结点指针后移指向新的尾部
			qa = qa->next; //qa指向下一个结点
		} 
		else{ //如果Lb中结点小,则Lb中结点插入
			pa->next = qb;  //将qb接到尾结点后面
			pa = qb;  //尾结点指针后移指向新的尾部
			qb = qb->next; //qb指向下一个结点
		}
	}
	
	/*如果La中还有剩余结点,则剩余结点继续尾插*/
	while(qa){ 
		pa->next = qa;  
		pa = qa; 
		qa = qa->next;
	}
	
	/*如果Lb中还有剩余结点,则剩余结点继续尾插*/
	while(qb){
		pa->next = qb;  
		pa = qb; 
		qb = qb->next;
	}
	 
	pa->next=NULL; //构造好的链表的尾结点置为空
		
	free(*Lb); //释放Lb结点的空间
	
	return 1;
}

/*归并两个递增单链表为一个递减单链表*/
int Algo_2(LinkList La, LinkList *Lb, LinkList *Lc){
	LinkList qa, qb, s;

	/*La或Lb有一个不存在或两个均为空表时,合并错误*/
	if(!La || !Lb || (!La->next && !(*Lb)->next))
		return 0;
	
	*Lc = La;	//利用La的头结点作Lc的头结点
	qa = La->next; //令qa指向La的首元结点
	qb = (*Lb)->next; //令qb指向Lb的首元结点
	La->next = NULL; //将La头结点的next置为空
	
	/*采用头插法建立递减链表*/
	/*谁小谁先插-->到最后小的在后面,大的在前面*/
	while(qa && qb){ //当La和Lb都未遍历完时
		if(qa->data<=qb->data){ //如果La中结点小,则La中结点插入
			s = qa->next;    //令s指向La中结点的next
			qa->next = La->next; //La中结点的next指向La头结点的next
			La->next = qa; //La头结点的next指向La中结点
			qa = s; //令qa继续指向La中的下一个结点
		} 
		else{ //如果Lb中结点小,则Lb中结点插入
			s = qb->next;  //令s指向Lb中结点的next
			qb->next = La->next; //Lb中结点的next指向La头结点的next
			La->next = qb; //La头结点的next指向Lb中结点
			qb = s; //令qb继续指向Lb中的下一个结点
		}
	}
	
	/*如果La中还有剩余结点,则剩余结点继续头插*/
	while(qa){ 
		s = qa->next;
		qa->next = La->next;
		La->next = qa;
		qa = s;
	}
	
	/*如果Lb中还有剩余结点,则剩余结点继续头插*/
	while(qb){
		s = qb->next;
		qb->next = La->next;
		La->next = qb;
		qb = s;
	}
		
	free(*Lb); //释放Lb结点的空间
	
	return 1;
}

/*递归法正序打印单链表【初始传入的L为首元结点】*/
void ListTraverse(LinkList L){
	if(L==NULL)  //递归的结束条件
		return;
	else{
		printf("%d ",L->data);  //先打印当前节点的数据
		ListTraverse(L->next); //递归单链表
	}
}

int main(){
	LinkList La, Lb, Lc;
	LinkList Ld, Le, Lf;
	int i;
	/*利用La和Lb的结点空间构造递增单链表Lc*/
	if(InitList_L(&La) && InitList_L(&Lb) && InitList_L(&Lc)){ 
		for(i=1; i<=5; i++){ //创建链表La和Lb
			ListInsert_L(La, i, 2*i-1);
			ListInsert_L(Lb, i, 2*i);		
		} 	
	}
	printf("创建好的链表为:\n");
	printf("La = ");
	ListTraverse(La->next); 	
	printf("\n");	
	printf("Lb = ");
	ListTraverse(Lb->next); 			
	printf("\n");	
	Algo_1(La, &Lb, &Lc);	
	printf("递增归并La和Lb为Lc = ");
	ListTraverse(Lc->next); 	
	printf("\n");			
	/*利用Ld和Le的结点空间构造递减单链表Lf*/
	if(InitList_L(&Ld) && InitList_L(&Le) && InitList_L(&Lf)){ 
		for(i=1; i<=5; i++){
			ListInsert_L(Ld, i, 2*i-1);
			ListInsert_L(Le, i, 2*i);		
		} 	
	}
	printf("创建好的链表为:\n");
	printf("Ld = ");
	ListTraverse(Ld->next); 	
	printf("\n");	
	printf("Le = ");
	ListTraverse(Le->next); 			
	printf("\n");	
	Algo_2(Ld, &Le, &Lf);	
	printf("递减归并Ld和Le为Lf = ");
	ListTraverse(Lf->next); 	
	printf("\n");			
	return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
循环单链表是一种特殊的单链表,其尾节点的指针指向头节点,形成一个环形结构。因此,连接两个循环单链表的过程和连接两个普通的单链表类似,只需要将第一个循环单链表的尾节点指向第二个循环单链表的头节点即可。 具体实现可以参考以下代码: ```c struct Node { int data; struct Node* next; }; typedef struct Node Node; // 连接两个循环单链表 Node* connect(Node* head1, Node* head2) { // 找到第一个循环单链表的尾节点 Node* tail1 = head1->next; while (tail1->next != head1) { tail1 = tail1->next; } // 找到第二个循环单链表的尾节点 Node* tail2 = head2->next; while (tail2->next != head2) { tail2 = tail2->next; } // 连接两个循环单链表 tail1->next = head2; tail2->next = head1; return head1; } ``` 其中,`head1`和`head2`分别表示两个循环单链表的头节点。首先,通过遍历找到两个循环单链表的尾节点`tail1`和`tail2`,然后将`tail1`的`next`指针指向`head2`,将`tail2`的`next`指针指向`head1`,这样就连接了两个循环单链表。最后返回第一个循环单链表的头节点`head1`,作为连接后的循环单链表的头。 使用示例: ```c Node* createList(int data[], int n) { Node* head = (Node*) malloc(sizeof(Node)); // 创建头节点 head->data = -1; head->next = head; // 初始化为空的循环单链表 for (int i = 0; i < n; i++) { Node* node = (Node*) malloc(sizeof(Node)); node->data = data[i]; node->next = head->next; // 新节点指向头节点的下一个节点 head->next = node; // 头节点指向新节点 } return head; } int main() { int data1[] = {1, 2, 3}; int data2[] = {4, 5, 6}; Node* head1 = createList(data1, 3); Node* head2 = createList(data2, 3); connect(head1, head2); // 遍历输出连接后的循环单链表 Node* p = head1->next; while (p != head1) { printf("%d ", p->data); p = p->next; } printf("\n"); return 0; } ``` 输出结果: ``` 1 2 3 4 5 6 ``` 可以看出,连接后的循环单链表中包括两个原来的循环单链表中的所有节点。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值