数据结构-链表篇

 数据结构 --链表

      一直想把写过的数据结构给整理下来,很久没写了。先分享下写过的链表操作相关的比较有趣的题(代码都是可以运行的)。后续会补充

1. 经典问题,链表中环的问题,我有一篇博客专门解释环的问题,这里就不啰嗦了,也就是快慢指针的原理。直接上代码:

环的入口:

/*

struct ListNode {

   int val;

   struct ListNode *next;

   ListNode(int x) :

       val(x), next(NULL) {

    }

};

*/

class Solution {

public:

   ListNode* EntryNodeOfLoop(ListNode* pHead)

    {

        ListNode* p1=pHead;

        ListNode* p2=pHead;

   //     ListNode* p3=pHead;

        if(pHead==NULL||pHead->next==NULL)

         return NULL;

        do{

         p1=p1->next;

        p2=p2->next->next;

    }while(p2!=NULL&&p2->next!=NULL&&p1!=p2);

  if(p1==p2)

      {

      p2=pHead;

    while(p2!=p1)

      {

     p2=p2->next;

     p1=p1->next;

    }

    return p1;

   }

   return NULL;


    }

};

 

2.约瑟夫圈圈问题(m>n可以)

已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。

通常解决这类问题时我们把编号从0~n-1,最后[1]  结果+1即为原问题的解。

/*

struct ListNode {

   int val;

   struct ListNode *next;

   ListNode(int x) :

       val(x), next(NULL) {

    }

};

*/

class Solution {

public:

   ListNode* EntryNodeOfLoop(ListNode* pHead)

    {

        ListNode* p1=pHead;

        ListNode* p2=pHead;

   //     ListNode* p3=pHead;

        if(pHead==NULL||pHead->next==NULL)

         return NULL;

        do{

         p1=p1->next;

        p2=p2->next->next;

    }while(p2!=NULL&&p2->next!=NULL&&p1!=p2);

  if(p1==p2)

      {

      p2=pHead;

    while(p2!=p1)

      {

     p2=p2->next;

     p1=p1->next;

    }

    return p1;

   }

   return NULL;


    }

};

 

3.合并两个排序的链表

输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。

/*

struct ListNode {

         intval;

         structListNode *next;

         ListNode(intx) :   val(x),next(NULL) {

         }

};*/

class Solution {

public:

   ListNode* Merge(ListNode* pHead1, ListNode* pHead2)

    {

       if(pHead1==NULL)

           return pHead2;

       if(pHead2==NULL)

           return pHead1;

       ListNode* pHead=NULL;  //保存新的头结点

       ListNode* p1=pHead1;   //为了写的方便,就将p1.p2替换原来的两个头结点

       ListNode* p2=pHead2;

       ListNode* pre=pHead1;

       ListNode* pT=NULL;

       if(p2->val<=p1->val){    //确定头结点

           pHead = p2;

           p2=p2->next;

           pHead->next=p1;

           pre = pHead;

                }

       else{

           pHead =p1;

           p1=p1->next;

           pre =pHead;

       }

              //将2插入1中

           while(p1!=NULL&&p2!=NULL){

                if(p2->val<p1->val){

                    pT=p2;

                    p2=p2->next;

                    pre->next=pT;

                    pT->next=p1;

                }

                else{

                   pre=p1;

                    p1=p1->next;

                }                

           }

           if(p1==NULL&&p2!=NULL){

           pre->next = p2;

           p2=p2->next;

            }

           if(p2==NULL&&p1!=NULL) {

                pre->next = p1;

                p1=p1->next;

               
           }

       return pHead;

    }

};

 

4. 从尾到头打印链表(面试题中经常会问的问题,写之前先问清楚是否可以改变链表的结构)

输入链表的表头,输出为需要打印的“新链表”的表头

/**

* struct ListNode {

*       int val;

*       struct ListNode *next;

*       ListNode(int x) :

*              val(x), next(NULL) {

*       }

*  };

*/

修改链表结构:

class Solution {

public:

   vector<int> printListFromTailToHead(struct ListNode* head) {

         vector<int> list1;

         if(head == NULL){

            

           return list1;

              }

       if(head->next==NULL)

       {

            list1.push_back(head->val);

           return list1;

       }

         ListNode* pri = head;  

         ListNode* cur = head->next;

         pri->next = NULL;

         ListNode* q = NULL;

       while(cur->next!=NULL)

           {

            q = cur;

            cur =cur->next;

            q->next = pri;

            pri=q;

       }

       cur->next=pri;   

       while(cur)

           {

           list1.push_back(cur->val);

           cur =cur->next;

       }

       return list1;

    }

};

利用栈(只不过内存消耗大,不推荐):

class Solution {

public:

   vector<int> printListFromTailToHead(struct ListNode* head) {

       vector<int> list1;

       if(head == NULL)      

           return list1;     

        stack<int> stack1;

       while(head)

           {

           stack1.push(head->val);

           head =head->next;

       }

       while(!stack1.empty()){

           list1.push_back(stack1.top());

       }

           

       return list1;

    }

};

只是逆序输出结点,不产生新表(递归):

 

vector<int>printListFromTailToHead(struct ListNode* head) {

       vector<int> v;

       while(head != NULL)

       {

           v.insert(v.begin(),head->val);

           head = head->next;

       }

       return v;

    }

 

class Solution {

public:

   vector<int> list1;

   vector<int> printListFromTailToHead(struct ListNode* head) {

        if(head==NULL)

            return list1;

      

        list1=printListFromTailToHead(head->next);     

        list1.push_back(head->val);

        return list1;

    }

};

 

5.反转链表

输入一个链表,反转链表后,输出链表的所有元素

/*

struct ListNode {

         intval;

         structListNode *next;

         ListNode(intx) :

                            val(x),next(NULL) {

         }

};*/

class Solution {

public:

   ListNode* ReverseList(ListNode* pHead) {

         if(pHead == NULL) return NULL;

         if(pHead->next==NULL) return pHead;

         ListNode* pri = pHead;  

         ListNode* cur = pHead->next;

         pri->next = NULL;

         ListNode* q = NULL;

       while(cur->next!=NULL)

           {

            q = cur;

            cur =cur->next;

            q->next = pri;

            pri=q;

       }

       cur->next=pri;      

       return cur;

    }

};

 

 

 

//栈

void print(listNode* head)

{

 std::stack<listNode*>nodes ;

 listNode* pnode = head ;

 while(pnode!=NULL)

{

  nodes.push(pnode);

  pnode = pnode->next;

}

while(!nodes.empty())

{

 listNode* p = nodes.top();

 cout<<p->data<<endl;

 nodes.pop();

}

 

}

 

//递归

 

void print(listNode* head)

{

 if(head!= NULL)

{

  

 if(head->next != null) 

{

 print(head->next);

}

 printf("%d\t",head->data);

}

}

 

6.设有一个带表头结点的双向循环链表L,每个结点有4个数据成员:指向先驱结点的指针prior、指向后继结点的指针next、

存放数据的成员data和访问频度freq。所有结点的freq初始时都为0.每当在链表上进行一次L.Locate(x)操纵时,

令元素值x的结点的访问频度freq加1,并将该结点前移,

链接到现它的访问频度相等的结点后面,使得链表中所有结点保持按访问频度递减的顺序排列,以使频繁访问的结点总是靠近表头。

 

voidLocate(int &x)

 {

 <结点类型说明 >

 *p =first->next;

 while (p != first &&  p->data!=x ) p = p->next;

 if(p != first)

 {

  p->freq++ ;

 <结点类型说明 >

 *current = p;

 current->prior->next = current->next;

 current->next->prior =current->prior;

 p =current->prior;

 while (p != first && p->freq <current->freq  ) p = p->prior;

 current->next = p->next  ;

 current->prior = p;

 p->next->prior = current;

 p->next = current;

 }

 else

 printf(“Sorry. Not find!\n”);  \*没找到*\

 }

 

7.输入一个链表,输出该链表中倒数第k个结点。

/*

struct ListNode {

         intval;

         structListNode *next;

         ListNode(intx) :

                            val(x),next(NULL) {

         }

};*/

class Solution {

public:

   ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {

       if(pListHead==NULL||k==0)

           return NULL;

      ListNode* p_temp = pListHead;  //一条用于从头遍历到k-1的位置

      ListNode* q = pListHead;

      int i=0;

      while( i<k-1) {

          p_temp = p_temp->next;

          i++ ;

          if(p_temp == NULL)

               return NULL;

      }

       while(p_temp->next!=NULL){

           p_temp = p_temp->next;

           q= q->next;

       }

       return q;

    }

};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值