记一道关于链表的面试题

  这几天一直在参加校园面试,各大公司都有自己的笔试题,一直以来都觉得链表题都比较简单,但有时候头脑发热,在紧张的笔试中再简单的算法题也有可能写不出来,近三天参加的笔试中,下面的链表题出现了三次,可见链表还是很重要的!

 
题目:

已知一链表结点定义为:

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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值