单链表

上次百度面试问到了单链表逆置的问题,和两个链表如何判相交的问题

现在有空把碰到过的跟单链表相关的面试题整理一下

 

1.单链表原地逆置

#include<iostream>
using namespace std;
class node
{
public:
    node(int n)
    {
        data = n;
     next = NULL; } node(){};
int data; node *next; }; class list { private: node* head; public: list() { head = new node(); head->next = NULL; } void add(node *n) { node *p = head; while(p->next!=NULL) { p = p->next; } p->next = n; } void show() { node *p = head; while(p->next!=NULL) { p = p->next; cout<<p->data<<endl; } } void reverse() { if(head->next == NULL) return; node *temp, *p, *pnext; p=head->next; pnext = p->next; p->next = NULL; while(pnext!=NULL) { temp = pnext->next; pnext->next = p; p = pnext; pnext = temp; } head->next = p; } }; int main() { list *l = new list(); l->add(new node(1)); l->add(new node(2)); l->add(new node(3)); l->add(new node(4)); l->add(new node(5)); l->add(new node(6)); l->show(); l->reverse(); cout<<"reverse"<<endl; l->show(); system("pause"); }

 

2.判断两个单链表是否相交

先考虑单链表没有环的情况

扩展:如果相交的话求出交点

#include<iostream>
using namespace std;
class node
{
public:
    node(int n)
    {
        data = n;
     next = NULL; } node(){};
int data; node *next; }; class list { private: node* head; public: list() { head = new node(); head->next = NULL; } void add(node *n) { node *p = head; while(p->next!=NULL) { p = p->next; } p->next = n; } void show() { node *p = head; while(p->next!=NULL) { p = p->next; cout<<p->data<<endl; } } node *getHead() { return head; } }; bool judge(node *a, node *b) { node *p = a->next; node *q = b->next; int cnta=0, cntb=0; while(p!=NULL) { cnta++; p = p->next; } while(q!=NULL) { cntb++; q = q->next; } if(cnta>cntb) { p=a->next; int step = cnta-cntb; while(step--) { p = p->next; } q = b->next; } else { q=b->next; int step = cntb-cnta; while(step--) { q = q->next; } p = a->next; } while(p->next!=NULL && q->next!=NULL) { if(p==q) { cout<<"cross point is "<<p->data<<endl; return 1; } else { p=p->next; q=q->next; } } cout<<"no cross"<<endl; return 0; } int main() { list *l = new list(); list *ll = new list(); node *a = new node(1);node *b = new node(2);node *c = new node(3); node *d = new node(4);node *e = new node(5);node *f = new node(6);node *g = new node(7);
l
->add(a);l->add(b);l->add(c);l->add(f);l->add(g); ll->add(d);ll->add(e);ll->add(c);ll->add(f);ll->add(g);
judge(l
->getHead(),ll->getHead());
list
*l1 = new list(); l1->add(a);l1->add(b);l1->add(c); list *l2 = new list(); l2->add(d);l2->add(e);l2->add(f);l2->add(g); judge(l1->getHead(), l2->getHead());
system(
"pause"); }

 

3.判断单链表是否有环

#include<iostream>
using namespace std;
class node
{
public:
    node(int n)
    {
        data = n;
        next = NULL;
    }
    node(){};
    int data;
    node *next;
};
class list
{
private:
    node* head;
public:
    list()
    {
        head = new node();
        head->next = NULL;
    }
    void add(node *n)
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
        }
        p->next = n;
    }
    void show()
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
            cout<<p->data<<endl;
        }
    }
    node *getHead()
    {
        return head;
    }
    bool isCircle()
    {
        node *p = head;
        node *q = head;
        while(q->next->next!=NULL && q->next!=NULL)
        {
            p = p->next;
            q = q->next->next;
            cout<<p->data<<" "<<q->data<<endl;
            if(p==q)
            {
                cout<<"circle exists"<<endl;
                return 1;
            }
        }
        cout<<"no circle exists"<<endl;
        return 0;
    }
};
int main()
{
    list *l = new list();list *ll = new list();
    node *a = new node(1);node *b = new node(2);node *c = new node(3);node *d = new node(4);
    node *e = new node(5);node *f = new node(6);node *g = new node(7);

    l->add(a);l->add(b);l->add(c);l->add(d);l->add(e);l->add(f);l->add(g);
    l->isCircle();
    l->add(e);
    l->isCircle();
    system("pause");
}

 扩展:

判断是否有环,如果有环的话找到环的入口

思路:假设单链表中有环,并且从链表头到环的入口长度为k,环的大小为n

在上述方法的基础上改进

可以把整个过程分为三步:

1.当较慢的指针走到环入口时走了k个位置,较快指针已经走了2k个,比较慢指针多走k个位置

2.在1的基础上较慢指针再走n-k个位置,此时较快指针又会多走n-k个位置,那么较快指针一共多走了n个位置,此时两指针相遇

3.在2的基础上,用一个新的指针从头开始和较慢指针同时前进,一次一个位置,两指针相遇时,刚好前进了k个位置,同时到达环的入口点。

#include<iostream>
using namespace std;
class node
{
public:
    node(int n)
    {
        data = n;
        next = NULL;
    }
    node(){};
    int data;
    node *next;
};
class list
{
private:
    node* head;
public:
    list()
    {
        head = new node();
        head->next = NULL;
    }
    void add(node *n)
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
        }
        p->next = n;
    }
    void show()
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
            cout<<p->data<<endl;
        }
    }
    node *getHead()
    {
        return head;
    }
    node *findCircleEntrance()
    {
        node *p = head;
        node *q = head;
        while(q->next->next!=NULL && q->next!=NULL)
        {
            p = p->next;
            q = q->next->next;
            cout<<p->data<<" "<<q->data<<endl;
            if(p==q)
            {
                cout<<"circle exists"<<endl;
                break;
            }
        }
        if(q->next->next!=NULL && q->next!=NULL)
        {
            node *t = head;
            while(t!=q)
            {
                t=t->next;
                q=q->next;
            }
            cout<<"the start of a circle is "<<t->data<<endl;
            return t;
        }
        cout<<"no circle exists"<<endl;
        return 0;
    }
};
int main()
{
    list *l = new list();
    list *ll = new list();
    node *a = new node(1);node *b = new node(2);node *c = new node(3);node *d = new node(4);
    node *e = new node(5);node *f = new node(6);node *g = new node(7);

    l->add(a);l->add(b);l->add(c);l->add(d);l->add(e);l->add(f);l->add(g);
    l->findCircleEntrance();
    l->add(d);
    l->findCircleEntrance();

    system("pause");
}

 

4.两个带环的链表求交点

如果两个链表相交,其中一个有环,那么另一个肯定也有环

上面已经找到了环的入口,那么沿着环绕一圈,如果能到另一个链表的环上,那么就是相交了,同时也能找到交点。

#include<iostream>
using namespace std;

class node
{
public:
    node(int n)
    {
        data = n;
        next = NULL;
    }
    node(){};
    int data;
    node *next;
};

class list
{
private:
    node* head;
public:
    list()
    {
        head = new node();
        head->next = NULL;
    }
    void add(node *n)
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
        }
        p->next = n;
    }
    void show()
    {
        node *p = head;
        while(p->next!=NULL)
        {
            p = p->next;
            cout<<p->data<<endl;
        }
    }
    node *getHead()
    {
        return head;
    }
    node *findCircleEntrance()
    {
        node *p = head;
        node *q = head;
        while(q->next!=NULL && q->next->next!=NULL)
        {
            p = p->next;
            q = q->next->next;
            if(p==q)
            {
                cout<<"circle exists"<<endl;
                break;
            }
        }
        if(p->next==NULL || p->next->next ==NULL)
        {
            cout<<"no circle exists"<<endl;
            return NULL;
        }
        if(q->next->next!=NULL && q->next!=NULL)
        {
            node *t = head;
            while(t!=q)
            {
                t=t->next;
                q=q->next;
            }
            cout<<"the start of a circle is "<<t->data<<endl;
            return t;
        }
        return NULL;
    }
};

bool judge(list *l, list *k)
{
    node *p = l->findCircleEntrance();
    node *q = k->findCircleEntrance();
    if(p==NULL || q==NULL)
    {
        cout<<"no cross"<<endl;
        return 0;
    }
    node *temp = p->next;
    while(temp != p)
    {
        if(temp == q)
        {
            cout<<"the cross is "<<temp->data<<endl;
            return 1;
        }
        else
            temp = temp->next;
    }
    return 0;
}

int main()
{
    list *l = new list();list *ll = new list();
    node *a = new node(1);node *b = new node(2);node *c = new node(3);node *d = new node(4);
    node *e = new node(5);node *f = new node(6);node *g = new node(7);

    l->add(a);l->add(b);l->add(c);l->add(d);l->add(e);l->add(b);
    ll->add(f);ll->add(g);ll->add(e);
    judge(l, ll);

    cout<<endl;
    list *lll = new list();
    node *h = new node(8);node *i = new node(9);
    lll->add(h);lll->add(i);
    judge(l,lll);

    system("pause");
}


这种方式只能判定交点在环上的情况

如果是交点不在环上,那么用前文中两个无环链表相交的方法可以判定

即在进入环之前找到交点

 

posted @ 2012-05-22 10:08  w0w0  阅读(227)  评论(0编辑  收藏  举报