c语言 将一升序链表和一降序链表合并为一个链表(7)

在这里插入图片描述
这道题我的思路就是:将那个降序的链表反转后,用上一题的代码,来将它们合并成一个降序的序列

单链表反转的两种方法

详情可以见这个博客:https://www.cnblogs.com/byrhuangqiang/p/4311336.html

?方法1:就地反转法

把当前链表的下一个节点pCur插入到头结点dummy的下一个节点中,就地反转。

dummy->1->2->3->4->5的就地反转过程:

dummy->2->1->3->4->5
dummy->3->2->1->4->5
dummy->4>-3->2->1->5
dummy->5->4->3->2->1

?方法2:新建链表,头节点插入法

新建一个头结点,遍历原链表,把每个节点用头结点插入到新建链表中。
最后,新建的链表就是反转后的链表。

本题答案:

#include<stdio.h>
#include<stdlib.h>
需知!
//这个程序的问题 l1只可以是增序,l2只可以是降序
//否则的话merge这个函数要修改
//merge函数用的是上一道题的代码
//有空的时候来修改一下merge函数

typedef struct node
{
	int data;
	struct node * next;

}Node;

typedef struct list
{
	Node* head;
	Node* tail;

}List;



void Init_list(List* L)
{
	Node* first = (Node*)malloc(sizeof(Node));
	if(!first)
		printf("wrong!\n");
	first -> data = 0;
	first -> next = NULL;
	L->head = L->tail = first;

	int length;

	printf("please enter list length: ");
	scanf("%d",&length); //scanf里面不能写类似于printf中打印字符串的语句
	for(int i = 0; i< length; i++)
	{
		Node* new = (Node*)malloc(sizeof(Node));
		scanf("%d",&new -> data); //这个语句注意一下

		new -> next = NULL;
		L->tail -> next = new;
		L->tail = new;

	}


}

//一个是升序 一个是降序 将其合并为一个有序的链表
//我想的方法是反转一个 然后再比较 (单链表的反转一般有两种,我选择的是原地反转)

void reverse_list(List* l)
{

	Node* prev; Node* pCur;
	prev = l -> head -> next;
	pCur = l -> head -> next -> next;//这两个节点的位置一定要确定好


	while(pCur != NULL)
	{
		prev -> next = pCur -> next;
		pCur -> next = l -> head -> next;
		l -> head -> next = pCur;
	
		//移动当前指针

		pCur = prev -> next;

	}
	

}

//我这里依旧选择原地合并
//都合并到l1中
//这里我偷懒用了上一题的代码,所以顺序是倒着的,反正题目只要求了有序
void merge(List* l1,List l2)
{
	reverse_list(&l2);
	
	Node *p,*q,*result;

	p = l1 -> head -> next; q = l2.head -> next;

	l1 -> head -> next = NULL; //让l1当作结果链 将结果链表最后一个指针指为空
	
	while(p!= NULL && q!= NULL)
	{
		if(p -> data <= q -> data) //合并时同时逆置
		{
			result = p -> next; //将p的后继节点暂存于result节点中
			p -> next = l1 -> head -> next; //将p节点链入结果表中,同时逆置
			l1 -> head -> next = p;
			p = result;
		}
		else
		{
			result = q -> next; //将p的后继节点暂存于result节点中
			q -> next = l1 -> head -> next ; //将p节点链入结果表中,同时逆置
			l1 -> head -> next  = q;
			q = result;
		}

	}

	if(p)      //避免对p再写下面的while操作
		q = p;

	while(q != NULL) //对一个剩余逆置,链入结果表中
	{
		result = q -> next; 
		q -> next = l1 -> head -> next ; 
		l1 -> head -> next  = q;
		q = result;
	}

}


void print_list(List L)
{
	Node* p;
	p = L.head->next;

	while(p != NULL)
	{
		printf("%d ",p->data);
		p = p -> next;
	}

	printf("\n");
}


int main(int argc, char const *argv[])
{
	List l1,l2;
	Init_list(&l1);
	Init_list(&l2);

	merge(&l1,l2);

	print_list(l1);

	return 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五月的天气

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值