面试训练链表问题

这种问题很经典,链表的求是否有环,以及链表数目为奇数或偶数返回中间节点,都可以不同步速率移动指针达到效果。非常棒

就地反转链表以前实习的时候遇到过一次,上次完全没准备什么东西,搞半天没有出结果。今天我来秒杀它

#include "stdio.h"
typedef struct Node{
	 int key;
	 struct Node *next;
}Lnode;
void buildLink(Lnode **head,int value)
{
	Lnode *q=NULL;
	Lnode *p = (Lnode *)malloc(sizeof(Lnode));
	p->next = NULL;
	p->key = value;
	if(*head == NULL)
	{
		*head = p;
	}
	else
	{
		q= *head;
		while(q->next != NULL)
		{
			q=q->next;
		}
		q->next =p;
	}

}
Lnode *reverseLink(Lnode *head)
{
	Lnode *p=NULL,*q=NULL,*r=NULL;
	if(head==NULL ||head->next == NULL)
	{
		return head;
	}
	p=head;
	q=p->next;
	r=q->next;
	if(r == NULL)
	{
		q->next=p;
		p->next=NULL;
		return q;
	}
	else
	{
		p->next=NULL;
		while(r!=NULL)
		{
			q->next=p;
			p=q;
			q=r;
			r=r->next;
		}
		q->next =p;
	}
	return q;
}
void freeList(Lnode *head)
{
	Lnode *p;
	while(head!=NULL)
	{
		p=head;
		head = head->next;
		free(p);
		p=NULL;
	}
}
int main()
{
	Lnode *head=NULL;
	Lnode *reverseHead = NULL;
	int totalNum =10;
	int index =0;
	int value;
	printf("total linknode num is: ");
	scanf("%d",&totalNum);
	for(;index<totalNum;index++)
	{
		scanf("%d",&value);
		buildLink(&head,value);
	}
	reverseHead = reverseLink(head);
	head = reverseHead;
	while(reverseHead != NULL)
	{
		printf("%d ",reverseHead->key);
		reverseHead = reverseHead->next;
	}
	freeList(head);
	return 0;
}
实现过程中使用三个指针p,q,r

当然需要考虑边界条件,只有一个节点或没有节点,或2个节点 需要特殊处理。

一般三个节点 只要p,q,r个指针就够了,r用来记录当前链表剩余节点的首节点,q是需要查到p之前的节点,所以q每次从r上面取节点,然后查到p之前,然后p节点移到q节点处,依次从后往前建立节点。

另外一种带头结点的 直接插入法就行,足够简单

代码实现比较简单,但是需要考虑到两个地方的问题,就是若两个链表有一个或两个为空的时候,需要特殊处理,不能直接往后遍历

考虑过这以后,就可以进行归并了。技巧方面主要就是需要先去一个节点作为第一个节点,以后只要向后遍历即可。代码如下

#include "stdio.h"
typedef struct Node{
	 int key;
	 struct Node *next;
}Lnode;
void buildLink(Lnode **head,int value)
{
	Lnode *q=NULL;
	Lnode *p = (Lnode *)malloc(sizeof(Lnode));
	p->next = NULL;
	p->key = value;
	if(*head == NULL)
	{
		*head = p;
	}
	else
	{
		q= *head;
		while(q->next != NULL)
		{
			q=q->next;
		}
		q->next =p;
	}

}
void freeList(Lnode *head)
{
	Lnode *p;
	while(head!=NULL)
	{
		p=head;
		head = head->next;
		free(p);
		p=NULL;
	}
}
Lnode *mergeLink(Lnode *head1,Lnode *head2)
{
	Lnode *p= NULL;
	Lnode *head=NULL;
	if(head1==NULL)
	{
		return head2;
	}
	if(head2==NULL)
	{
		return head1;
	}
	if(head1->key<=head2->key)
	{
		p=head1;
		head1=head1->next;
	}
	else
	{
		p=head2;
		head2=head2->next;		
	}
	head = p;
	while(head1!=NULL&&head2!=NULL)
	{
		if(head1->key<=head2->key)
		{
			p->next=head1;
			head1=head1->next;
			p=p->next;
		}
		else
		{
			p->next = head2;
			head2=head2->next;
			p=p->next;
		}
	}
	if(head1!=NULL)
	{
		p->next=head1;
	}
	if(head2!=NULL)
	{
		p->next=head2;
	}
	return head;
}
int main()
{
	Lnode *head1=NULL;
	Lnode *head2= NULL;
	Lnode *head = NULL;
	Lnode *traverse=NULL;
	int totalNum =10;
	int index =0;
	int value;
	printf("total linknode num is: ");
	scanf("%d",&totalNum);
	for(index=0;index<totalNum;index++)
	{
		scanf("%d",&value);
		buildLink(&head1,value);
	}
	printf("total linknode num is: ");
	scanf("%d",&totalNum);
	for(index=0;index<totalNum;index++)
	{
		scanf("%d",&value);
		buildLink(&head2,value);
	}
	head = mergeLink(head1,head2);
	traverse =head;
	while(traverse != NULL)
	{
		printf("%d ",traverse->key);
		traverse = traverse->next;
	}
	freeList(head);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值