• 面试题:单链表的几种处理


    首先链表节点的定义如下:

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

    面试题1:创建一个单链表

    功能函数:

    /****创建带有头结点的单链表******/
    Node *creat(int n)
    {
        Node *head,*p,*q;
        int x;
        head=(Node *)malloc(sizeof(Node)); /*创建头结点*/
    
        q=head;
    
        if(n>0)
        {
            printf("Please input the data of the node:");
            while(n>0)
            {
                scanf("%d",&x);
                p=(Node *)malloc(sizeof(Node));
                p->data=x;
                q->next=p;
                q=p;
                n--;
            }
        }
        q->next=NULL;
        return head;
    }

    面试题2:编程实现单链表的打印

    功能函数:

    /****打印单链表******/
    void print(Node *head)
    {
        Node *p;
        if(head->next==NULL)
        {
            printf("The LinkList is Empty !
    ");
            return;
        }
        p=head->next;
        while(p!=NULL)
        {
            printf("%d ",p->data);
            p=p->next;
        }
    }

    面试题3:编程实现从尾到头打印单链表(剑指offer)

    思路1:第一反应是将链表中的指针反转,改变链表的方向,然后再从头打印出来(该方法改变了原来链表的结构,这就要看面试或笔试时的要求,可否改变链表结构)

    思路2:遍历链表时是从头到尾,而打印链表时却是从尾到头,典型的“先进后出”——栈的特点,从而可以用栈来实现。没遍历一个节点,把该节点放到一个栈中,当遍历完整个链表后,再从栈顶开始逐个输出节点的值,此时输出的节点顺序已经反转过来了。

    思路3:栈可以实现,而递归本质上也是一个栈结构,从而可以用递归来实现。即:没遍历到一个节点时,先递归输出其后面的一个节点的值,再输出该节点本身的值。

    功能函数(思路3):

    void Rev_print(Node *head)  
    { 
        Node *p;
        if(head==NULL || head->next==NULL)
            return;
        else
        {
            p=head->next;
            Rev_print(p);  
            printf("%d ",p->data);
        }
    }  

     面试题4:编程实现查找单链表的中间节点

    解题思路:A和B赛跑,其中A的速度是B的速度的两倍,当A到达终点时,B刚好到达中点

    功能函数:

    Node *find_midNode(Node *head)
    {
        Node *p1,*p2;
    
        if(head==NULL || head->next==NULL) //链表为空,或是单结点链表直接返回头结点
            return head;
    
        p1=p2=head->next;
    
        while(1)
        {
            if(p2->next!=NULL && p2->next->next!=NULL)
            {
                p2=p2->next->next;
                p1=p1->next;
            }
            else
                break;
        }
        return p1;
    }

    面试题5:编程实现查找单链表的倒数第k个节点

    思路1:首先求出单链表总的长度n,然后从链表的头节点开始遍历,当遍历到n-m个节点时,即为链表中倒数第m个节点

    思路2:首先设置两个指针p1和p2,同时指向单链表的头节点,然后用p2遍历链表,将p2指向链表中第m个节点,接着将p1和p2同时进行遍历,当p2指向链表中末尾节点时,p1所指向的节点即为倒数第m个节点。

    功能函数(思路1):

    Node *Find_Rev_node_1(Node *head,int k)  //思路1
    {
        Node *p;
        int n=0,i;
        p=head;
        while(p!=NULL)
        {
            n++;
            p=p->next;
        }
    
        if (n==0 || k>n)
        {
            return NULL;
        }
        
        p=head;
        for(i=0;i<n-k;i++)
        {
            p=p->next;
        }
        return p;
    }

    功能函数(思路2):

    Node *Find_Rev_node_2(Node *head,int k)  //思路2
    {
        Node *p,*p1,*p2;
        int n=0,i;
    
        p=head;
        while(p!=NULL)
        {
            n++;
            p=p->next;
        }
    
        if (n==0 || n<k)
        {
            return NULL;
        }
        p1=p2=head;
        for(i=0;i<k;i++)
        {
            p2=p2->next;
        }
        while(p2)
        {
            p2=p2->next;
            p1=p1->next;
        }
        return p1;
    }

    面试题6:编程实现判断单链表是否存在环形链表问题

     思路:使用快慢指针,慢指针每次只前进一步,快指针每次前进两步,直到慢指针遇上快指针。分别设置两个指针p1,p2.每循环一次,p2前进两步,p1前进一步,直到p2与p1相等或p2碰到NULL时结束。如果两个指针相等,则说明存在回环。

    功能函数:

    int Isloop_LinkList(Node *head)
    {
        Node *p1,*p2;
        if(head==NULL || head->next==NULL) //链表为空,或是单结点链表直接返回头结点
            return 0;
        p1 = p2 = head;
        while(p2->next!=NULL && p2->next->next!=NULL)
        {
            p1=p1->next;
            p2=p2->next->next;
            if(p1==p2)
                return 1;
        }
        return 0;
    }

     面试题7:编程实现单链表的逆置

     思路:遍历一遍链表,利用一个辅助指针保存当前节点的下一个节点,然后将当前节点的指针反转,利用已经存储的指针往后继续遍历

    功能函数: 

    Node *reverse_LinkList(Node *head)
    {
        Node *p,*q,*r;
    
        if(head==NULL || head->next==NULL)  //链表为空,或是单结点链表直接返回头结点
            return head;
    
        p=head->next; //第一个节点
        q=p->next;    //保存第二个节点
        p->next=NULL;   //原第一个节点为末节点
    
        while(q!=NULL)
        {
            r=q->next;
            q->next=p;
            p=q;
            q=r;
        }
        head->next=p; //新的第一个节点为原末节点
        return head;
    }

     测试程序:

    头文件:

    #include<stdio.h>
    #include<stdlib.h>

    主函数:

    int main()
    {
        int len,k;
        int flag=0;
        Node *LinkList,*Rev_LinkList;
        Node *a,*b,*c;
    
        printf("Please input the length of the LinkList:");
        scanf("%d",&len);
        LinkList=creat(len);
        printf("创建的链表如下:
    ");
        print(LinkList);
        printf("
    ");
    
        printf("从尾到头打印链表如下:
    ");
        Rev_print(LinkList); 
        printf("
    ");
    
        a=find_midNode(LinkList);
        printf("The middle node of the LinkList is:");
        printf("%d
    ",a->data);
        printf("
    ");
    
        printf("思路1:请输入要查找的倒数第几个节点? ");
        scanf("%d",&k);
        b=Find_Rev_node_1(LinkList,k);
        printf("链表的倒数第%d个节点为:",k);
        printf("%d
    ",b->data);
        printf("
    ");
    
        printf("思路2:请输入要查找的倒数第几个节点? ");
        scanf("%d",&k);
        c=Find_Rev_node_2(LinkList,k);
        printf("链表的倒数第%d个节点为:",k);
        printf("%d
    ",c->data);
        printf("
    ");
    
        flag=Isloop_LinkList(LinkList);
        if(flag==1)
            printf("该链表存在回环!
    ");
        else
            printf("该链表不存在回环!
    ");
    
        printf("链表反转后新的链表如下:
    ");
        Rev_LinkList=reverse_LinkList(LinkList);
        print(Rev_LinkList);
        printf("
    ");
        system("pause");
        return 1;
    }

    测试结果:

  • 相关阅读:
    win2008服务器信任问题
    切换cmd的目录
    c#后的完整cookie
    c#网络编程-第一章
    c#访问mysql数据库
    标准库hashlib模块
    标准库ConfigParser模块
    标准库shutil
    标准库 xml
    标准库shelve
  • 原文地址:https://www.cnblogs.com/kkdd-2013/p/3353773.html
Copyright © 2020-2023  润新知