zoukankan      html  css  js  c++  java
  • 程序员面试笔试——链表题目总结分析

    本文计划分析的链表题目:

    单链表相关

    1. 单链表创建
    2. 单链表节点删除
    3. 单链表出入节点
    4. 单链表逆转
    5. 单链表是否有环,若有,求环的第一个节点。
    6. 两个单链表是否相交,若有环,无环?
    7. 单链表排序

    双链表相关

    1. 双链表创建
    2. 双链表节点删除
    3. 双链表节点插入
    4. 双链表与二元查找树

    单链表:

    链表节点结构

    typedef struct Snode
    {
        int  data;
        struct Snode* next;
    } SLinkNode;

    1.单链表创建

    单链接的创建,采用后接方式,即后插入节点在后面,先插入节点在前面:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <memory.h>
     4 
     5 typedef struct Snode{
     6     int  data;
     7     struct Snode* next;
     8 }SLinkNode;
     9 
    10 
    11 int main(int argc, char *argv[])
    12 {
    13     int arr[] = {6,9,23,56,88,797,67,34,76,343};
    14     SLinkNode* head = NULL;
    15     SLinkNode* pre, *cur;
    16     int i= 0,j =0;
    17     for( i = 0; i<10 ; ++i ){
    18         printf("%d	", arr[i]);
    19     }
    20     puts("
    ");
    21 
    22 
    23 
    24     for(i =0 ;i < 10 ; ++i ){
    25         cur = (SLinkNode *) malloc(sizeof (SLinkNode));
    26         cur -> data = arr[i];
    27         cur -> next = NULL;
    28         if(head == NULL){
    29             head = pre = cur ;
    30         }else{
    31             pre ->next = cur;
    32             pre = cur;
    33         }
    34     }
    35 
    36     cur = head;
    37     while(cur != NULL){
    38         printf("%d	", cur ->data);
    39         cur = cur ->next;
    40     }
    41 
    42     return 0;
    43 }
    创建单链表

    2、单链表节点删除

    单链表节点删除,单链表的节点删除方法相对简单

    主要遇到的问题有:

    1. 给定链表中一个指针,要求删除该节点(若不是尾节点,与后续节点交换数据,否则,还是需要遍历)
    2. 其他

    3、单链表插入节点

    单链接节点插入也相对简单,主要遇到问题

    1. 在当前节点之前插入节点,如何进行(创建新节点,也当前节点交换数据)
    2. 其他。

    4、单链表逆转

    单链表的逆转:

     1 SLinkNode* reverseLink(SLinkNode* head)
     2 {
     3     if(head == NULL || head->next == NULL)
     4     {
     5        return head;   /*链表为空或只有一个元素则直接返回*/
     6     }
     7 
     8     SLinkNode *tmp = NULL,
     9               *pre = head,
    10               *cur = head -> next;
    11     while(cur  != NULL)
    12     {
    13       tmp = cur->next;
    14       cur->next = pre;
    15       if( pre == head ){
    16         pre -> next = NULL;
    17       }
    18       pre = cur;
    19       cur = tmp;
    20     }
    21 
    22     head = pre ;
    23     return head;
    24 }

    5、单链表是否有环,若有,求环的第一个节点。

    创建含有环的单链表

        SLinkNode*  cycleNode ;
    
        for(i =0 ; i < 10 ; ++i )
        {
            cur = (SLinkNode *) malloc(sizeof (SLinkNode));
            cur -> data = arr[i];
            cur -> next = NULL;
            if(head == NULL)
            {
                head = pre = cur ;
            }
            else
            {
                pre ->next = cur;
                pre = cur;
            }
            if(i ==5 ){
                cycleNode = pre;
            }
        }
    
        cur -> next = cycleNode;

    利用两一个指针,一个速度是另外一个的两倍。

    即一个指针慢指针:每次移动一个结点;一个快指针,每次移动两结点。

    若有环:则两指针会在某一点相遇;若无环:则快指针会先走到链表末尾。

    代码如下:

    int isCircleLink(SLinkNode* head)
    {
        if(head == NULL ||  head ->next == NULL)
        {
            return 0;
        }
    
        SLinkNode  *slow = head,
                    *fast = head;
    
        while (fast && fast-> next)
        {
            slow = slow ->next;
            fast = fast ->next -> next;
            if (slow == fast)
            {
                return 1;
            }
        }
        return 0;
    
    }

    求含有环单链表的环汇总第一个节点:

    解法一 :

    假设快指针和慢指针在蓝色圆圈所表示结点p处相遇,则它们走过的路径长度分别为:

    快指针fast = 非环段链表长度L  + 环上链表结点个数C +   从p到交点的弧长S

    慢指针slow = 非环段链表长度L +   从p到交点的弧长S

    又有fast = 2*slow

    故 L = C - S

    因此:设两个指针,一个从表头开始遍历,一个从p开始遍历,相遇的结点就是环的起点。代码如下:

    SLinkNode* beginOfCircle(SLinkNode *head)
    {
        if( head == NULL || head -> next == NULL)
        {
            return NULL;
        }
    
        SLinkNode  *slow = head,
                    *fast = head;
    
        while (fast && fast-> next)
        {
            slow = slow ->next;
            fast = fast ->next -> next;
            if (slow == fast)
            {
                break;
            }
        }
    
        if(fast == NULL || fast->next == NULL)          //此时链表无环;
        {
            return NULL;
        }
    
        fast = head;
        while (slow != fast)
        {
            slow = slow-> next;
            fast  = fast-> next;
        }
        return fast;
    }

     两外一种思路,求两个链表的共同点

    SLinkNode* beginOfCircle2(SLinkNode *head)
    {
        if( head == NULL || head -> next == NULL)
        {
            return NULL;
        }
    
        SLinkNode  *slow = head,
                    *fast = head;
    
        while (fast && fast-> next)
        {
            slow = slow ->next;
            fast = fast ->next -> next;
            if (slow == fast)
            {
                break;
            }
        }
    
        if(fast == NULL || fast->next == NULL)          //此时链表无环;
        {
            return NULL;
        }
    
        fast = slow ->next ;
        slow -> next = NULL;
        int len1 = 0;
        int len2 = 0;
        slow = head ;
        while(slow != NULL)
        {
            len1++;
            slow =slow-> next;
        }
    
        slow = fast ;
        while(slow != NULL)
        {
            len2++;
            slow =slow-> next;
        }
        int len = 0 ;
        if(len1 > len2)
        {
            len = len1 -len2 ;
            slow = head;
            while(slow !=NULL  && len >0)
            {
                --len;
                slow = slow -> next;
            }
            while(fast != NULL && slow != NULL && fast != slow ){
                fast = fast ->next;
                slow = slow -> next;
            }
            if(fast == slow){
                return fast;
            }else{
                return NULL;
            }
        }else if(len1 < len2){
            len = len2 -len1 ;
    
            while(fast != NULL && len >0 )
            {
                -- len;
                fast = fast -> next;
            }
            slow = head;
            while(fast != NULL && slow != NULL && fast != slow ){
                fast = fast ->next;
                slow = slow -> next;
            }
            if(fast == slow){
                return fast;
            }else{
                return NULL;
            }
        }else{
            slow = head;
            while(fast != NULL && slow != NULL && fast != slow ){
                fast = fast ->next;
                slow = slow -> next;
            }
            if(fast == slow){
                return fast;
            }else{
                return NULL;
            }
        }
    }

    6、两个单链表是否相交,若有环,无环?

    4、判断链表是否相交

    a、无环链表情况:

    方法1:把链表的尾结点和另外一个链表的起点链接起来,然后判断是否有环。代码如下:
    bool isCross(List head1, List head2)
    {
        assert(head1 && head2);
        List p1 = head1;
       while (p1->link)
          p1 = p1->link;
      p1->link = head2;
      if (hasCircle(head1))
         return true;
      return false;
    }
    方法2:如果两个无环链表相交,其尾节点必然相等!代码如下:
    bool isCross(List head1, List head2)
    {
       assert(head1 && head2);
       while (head1->link)
           head1 = head1->link;
       while (head2->link)
          head2 = head2->link;
      if (head1 == head2)
         return true;
      return false;
    }
     
    b.有环链表相交
    解法:有环链表相交,两必然有同一个环;可设一快指针,一慢指针,在绕环N圈后,快指针必然遇到慢指针。代码如下:
    bool isCross_(List head1, List head2)
    {
       bool isCross = false;
       assert(head1 && head2);
       List fast = head1, slow = head2;
       while (fast && fast->link)
       {
            fast =  fast->link->link;
            slow = slow->link;
            if (slow && slow == fast)
            {
                  isCross = true;
                  break;
            }
       }
       return isCross;
    }
     求交点都可以转化为求环的起点问题。
    无环->链表首尾相接;
    有环->交点一个或者两个;
     
    参考
    http://oyjh1986.blog.163.com/blog/static/19601607620118293262941/
     

    单链表排序

    单列一篇。

    双链表相关

    双链表创建

    双链表节点删除

    双链表节点插入

    双链表与二元查找树

  • 相关阅读:
    第一次软件作业
    第四次作业之单元测试
    第四次作业之代码规范
    第四次作业之psp
    第四次作业之四则运算
    第三周作业之功能测试
    第三周作业之效能分析
    第三周作业之例行报告
    第二周例行报告(王伟东)
    软件工程第二次作业(王伟东)
  • 原文地址:https://www.cnblogs.com/xuddong/p/3322645.html
Copyright © 2011-2022 走看看