数据结构-链表篇

来源:互联网 发布:ubuntu用u盘安装 编辑:程序博客网 时间:2024/06/06 07:06

 数据结构 --链表

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

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;    }};


1 0
原创粉丝点击