这几天一直在参加校园面试,各大公司都有自己的笔试题,一直以来都觉得链表题都比较简单,但有时候头脑发热,在紧张的笔试中再简单的算法题也有可能写不出来,近三天参加的笔试中,下面的链表题出现了三次,可见链表还是很重要的!
题目:
已知一链表结点定义为:
typedef struct node Node;
struct node
{
int data;
Node *next;
};
(1) 现已知链表头head,请写一函数,逆转该链表;
(2) 现有两个有序链表,它们的头结点为head_a, head_b,请合并他们,让合并后的链表依然有序;
(3) 在题目二的基础上,采用递归的方法合并链表;
解答:
(1) 现已知链表头head,请写一函数,逆转该链表;
//逆序一个链表
Node *Reverse(Node *head)
{
if((head == NULL) || (head->next == NULL))
return head;
Node *p1 = head;
Node *p2 = p1->next;
Node *p3 = p2->next;
p1->next = NULL;
while(p3 != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
return p2;
}
(2) 现有两个有序链表,它们的头结点为head_a, head_b,请合并他们,让合并后的链表依然有序;
//循环方式合并两个有序链表
Node *MergeList(Node *head_a, Node *head_b)
{
if(head_a == NULL)
return head_b;
if(head_b == NULL)
return head_a;
Node *newhead = NULL;
Node *pa = NULL;
Node *pb = NULL;
if(head_a->data <= head_b->data)
{
newhead = head_a;
pa = newhead->next;
pb = head_b;
}
else
{
newhead = head_b;
pb = newhead->next;
pa = head_a;
}
Node *pcurrent = newhead;
while((pa != NULL) && (pb != NULL))
{
if(pa->data <= pb->data)
{
pcurrent->next = pa;
pcurrent = pcurrent->next; //pcurrent = pa;
pa = pa->next;
}
else
{
pcurrent->next = pb;
pcurrent = pcurrent->next;
pb = pb->next;
}
}
if(pa != NULL)
{
pcurrent->next = pa;
}
if(pb != NULL)
{
pcurrent->next = pb;
}
return newhead;
}
(3) 在题目二的基础上,采用递归的方法合并链表;
//递归方式合并两个有序链表
Node *Recursive_MergeList(Node *head_a, Node *head_b)
{
if(head_a == NULL)
return head_b;
if(head_b == NULL)
return head_a;
Node *newhead = NULL;
if(head_a->data <= head_b->data)
{
newhead = head_a;
newhead->next = Recursive_MergeList(head_a->next,head_b);
}
else
{
newhead = head_b;
newhead->next = Recursive_MergeList(head_a,head_b->next);
}
return newhead;
}
测试:
#include <stdio.h>
#include <malloc.h>
typedef struct node Node;
struct node
{
int data;
Node *next;
};
Node *CreateList()
{
Node *head = (Node*)malloc(sizeof(Node));
if(head != NULL)
{
head->data = 0; //记录链表长度
head->next = NULL;
}
return head;
}
int InsertList(Node *head, int data,unsigned int pos)
{
int iret = -1;
if(head == NULL)
return iret;
//调整插入的位置
pos = pos > head->data ? head->data : pos; //头节点后的第一个节点从0开始编号
Node *temp = (Node*)malloc(sizeof(Node));
if(temp == NULL)
return iret;
temp->data = data;
temp->next = NULL;
iret = 0;
Node *current = head;
for(int i = 0; i < pos; i++)
{
current = current->next;
}
temp->next = current->next;
current->next = temp;
head->data++;
return iret;
}
unsigned int GetListLength(Node *head)
{
if(head == NULL)
return -1;
return head->data;
}
//打印链表信息
void Display(Node *head,int len)
{
if(head == NULL)
return;
Node *current = head;
for(int i = 0; i < len; i++)
{
printf("%d\t", current->data);
current = current->next;
}
printf("\n");
}
int main()
{
Node *head_b = CreateList();
InsertList(head_b,0,0);
InsertList(head_b,2,1);
InsertList(head_b,4,2);
InsertList(head_b,6,3);
InsertList(head_b,8,4);
InsertList(head_b,10,5);
int len_b = GetListLength(head_b);
printf("head_b:\n");
Display(head_b->next,len_b);
Node *head_a = CreateList();
InsertList(head_a,1,0);
InsertList(head_a,3,1);
InsertList(head_a,5,2);
InsertList(head_a,7,3);
InsertList(head_a,9,4);
InsertList(head_a,11,5);
InsertList(head_a,12,6);
int len_a = GetListLength(head_a);
printf("head_a:\n");
Display(head_a->next,len_a);
//逆序链表
// head_a->next = Reverse(head_a->next);
// Display(head_a->next,len_a);
//循环方式合并链表
// Node *mergehead = (Node*)malloc(sizeof(Node));
// if(mergehead == NULL)
// return -1;
// mergehead->data = len_b + len_a;
// mergehead->next = MergeList(head_b->next, head_a->next); //注意不能直接传递头结点
// int len_m = GetListLength(mergehead);
// printf("mergehead:\n");
// Display(mergehead->next,len_m);
//递归方式合并
Node *recursivehead = (Node*)malloc(sizeof(Node));
if(recursivehead == NULL)
return -1;
recursivehead->data = len_b + len_a;
//注意不能直接传递头结点
recursivehead->next = Recursive_MergeList(head_b->next, head_a->next);
int len_r = GetListLength(recursivehead);
printf("recursivehead:\n");
Display(recursivehead->next,len_r);
return 0;
}