<剑指offer>之链表题目

来源:互联网 发布:凯立德端口检测工具 编辑:程序博客网 时间:2024/04/30 03:18

【引言】

   这几天在看<剑指offer>写的很好,跟July的各有千秋,更加注重归纳总结,笔试面试临时抱佛脚,决定要啃下这其中的46道题目。OK,把每道题目自己实现,相同的归成一类。这次把所有的与list相关的题目列出来。

【题目5】从尾到头打印list

//思路:从尾到头打印list的话,考虑用stack先把各节点保存起来,遍历完以后再将stack弹出打印即可
[cpp] view plaincopy
  1. #include <stack>  
  2. void print_list_reverse(list_node* head)  
  3. {  
  4.     stack<char> m_list;  
  5.     if (head == NULL)  
  6.         return;  
  7.     list_node* node = head->m_pNext;  
  8.     while(node != NULL)  
  9.     {  
  10.         m_list.push(node->m_data);  
  11.         node = node->m_pNext;  
  12.     }  
  13.     while(!m_list.empty())  
  14.     {  
  15.         cout<<m_list.top()<<" ";  
  16.         m_list.pop();  
  17.     }  
  18. }  
//思路:用递归模拟stack,每次遍历list当前节点的时候,递归调用下一个节点,直到list结尾
[cpp] view plaincopy
  1. void print_list_reverse_res(list_node* head)  
  2. {  
  3.     if (head == NULL)  
  4.         return;  
  5.     list_node* node = head;  
  6.     if (node->m_pNext != NULL)  
  7.     {  
  8.         node = node->m_pNext;  
  9.         print_list_reverse_res(node);  
  10.         cout<<node->m_data<<" ";  
  11.     }  
  12. }  

【题目13】在O(1)时间内删除链表节点

//void delete_node_O1(list_node* head, list_node* pto_delete)函数形式;可以看出,已经给出了要删除node的指针,我们可以很方便地找到要删除node的下一个node
//将下一个node的信息复制到当前node,再将下一个node删除,这正好相当于将当前node删除!时间复杂度是O(1),需要注意的是假设当前node是最后一个的话
//node->next为空,上面的思路就不行了,我们还是需要找到尾节点的上一个节点!如果所有链表只有一个节点,那么我们将head置空即可。so,代码如下:
[cpp] view plaincopy
  1. void delete_node_O1(list_node* head, list_node* pto_delete)  
  2. {  
  3.     if (pto_delete == NULL || head == NULL)  
  4.         return;   
  5.     list_node* nextNode;  
  6.     if (pto_delete->m_pNext != NULL)  
  7.     {  
  8.         nextNode = pto_delete->m_pNext;  
  9.         pto_delete->m_data = nextNode->m_data;  
  10.         pto_delete->m_pNext = nextNode->m_pNext;  
  11.         delete nextNode;  
  12.         nextNode = NULL;  
  13.           
  14.     }  
  15.     else if (pto_delete == head)  
  16.     {     
  17.         delete pto_delete;  
  18.         pto_delete = NULL;  
  19.         head = NULL;  
  20.     }  
  21.     else //list尾,没办法,要将前一个节点的m_pNext置为NULL只能遍历一次  
  22.     {  
  23.         list_node* node = head;  
  24.         while(node->m_pNext != pto_delete)  
  25.             node = node->m_pNext;  
  26.         nextNode = node->m_pNext;  
  27.         node->m_pNext = NULL;      
  28.         delete nextNode;  
  29.         nextNode = NULL;  
  30.     }  
  31.   
  32. }  

【题目15】寻找list中倒数第k个节点

//题目给出一个list,输出该链表中倒数第k个节点。
//为符合习惯本题目,从1开始计数,即list的最后一个节点是倒数第一个
//思路:使用两个指针,刚开始同时指向list头,然后第二个指针p2前进k-1步,然后第一个指针p1和p2
//同时前进,知道p2到达list尾,这时p1指向倒数第k个节点
[cpp] view plaincopy
  1. list_node* find_k_reverse(list_node* head, int k)  
  2. {  
  3.     if (head == NULL || k < 1)  
  4.         return NULL;  
  5.     list_node *p1, *p2;  
  6.     p1 = p2 = head;  
  7.     int i = 0;  
  8.     while(p2->m_pNext != NULL && (++i != k))  
  9.         p2 = p2->m_pNext;  
  10.     if (p2->m_pNext == NULL)//list长度小于k-1  
  11.         return NULL;  
  12.     while(p2->m_pNext != NULL)  
  13.     {  
  14.         p1 = p1->m_pNext;  
  15.         p2 = p2->m_pNext;  
  16.     }  
  17.     return p1;  
  18.   
  19. }  

【题目16】反转list

//给定一个list,输入参数是头结点,要求反转list,输出翻转后list的头结点
//这类问题,都不难,最好画画图啥的,需要注意的中间需要一些节点保存指针,要不会造成list的断裂,需要三个指针,当前指针,当前指针前一个指针,当前指针后一个指针
[cpp] view plaincopy
  1. list_node* reverse_list(list_node* head)  
  2. {  
  3.     if (head == NULL)  
  4.         return NULL;  
  5.     //一共需要三个指针,当前节点之前,当前节点,当前节点之后的节点,这样才不会造成  
  6.     //调整过程中的list的断裂  
  7.     list_node* p_node = head;  
  8.     list_node* p_pre = NULL;  
  9.     list_node* p_next = p_node->m_pNext;  
  10.     while (p_next != NULL)  
  11.     {  
  12.         p_node->m_pNext = p_pre;  
  13.         p_pre = p_node;  
  14.         p_node = p_next;  
  15.         p_next = p_next->m_pNext;  
  16.     }  
  17.     if (p_next == NULL)//这个时候p_node就是原来的尾节点  
  18.     {  
  19.         p_node->m_pNext = p_pre;  
  20.     }  
  21.     return p_node;    
  22.   
  23. }  

【题目17】合并两个有序list

[cpp] view plaincopy
  1. list_node* merge_order_list(list_node* first, list_node* second)  
  2. {  
  3.     //有链表为空的情况  
  4.     if(first == NULL)  
  5.         return second;  
  6.     if(second == NULL)  
  7.         return first;  
  8.     list_node* p_result = NULL;  
  9.     if (first->m_data < second->m_data)  
  10.     {  
  11.         p_result = first;  
  12.         p_result->m_pNext = merge_order_list(first->m_pNext, second);  
  13.     }  
  14.     else  
  15.     {  
  16.         p_result = second;  
  17.         p_result->m_pNext = merge_order_list(first, second->m_pNext);  
  18.     }  
  19.     return p_result;          
  20.   
  21. }  

0 0
原创粉丝点击