zoukankan      html  css  js  c++  java
  • 链表中倒数第K个结点

    题目:输入一个链表,输出该链表中倒数第K个结点。为了符合大多数人的习惯,本题从1开始计数,即链表的尾结点是倒数第1个结点。例如一个链表有6个结点,从头结点开始它们的值依次是1、2、3、4、5、6。这个链表的倒数第3个结点是值为4的结点。

    思路:设定两个指针p1和p2,两个指针刚开始都指向链表的第一个结点,然后让p1指针先走(k-1)步,然后再让两个指针一起往后走,当p1指针指向链表最后一个结点的时候,p2指针刚好指向链表中的倒数第k个结点。

    在写代码的时候需要考虑鲁棒性,最好采用防御性编程,就是考虑在哪些地方会出错,然后提前加上错误判断,这样避免因此错误输入而导致程序崩溃。

      1 #include<iostream>
      2 #include<stdio.h> 
      3 #include<tchar.h>
      4 using namespace std;
      5 
      6 //链表结构
      7 struct ListNode
      8 {
      9     int m_nValue;
     10     ListNode* m_pNext;
     11 };
     12 
     13 //创建一个链表结点
     14 ListNode* CreateListNode(int value)
     15 {
     16     ListNode* pNode = new ListNode();
     17     pNode->m_nValue = value;
     18     pNode->m_pNext = NULL;
     19 
     20     return pNode;
     21 }
     22 
     23 //输出链表中的某一结点的值
     24 void PrintListNode(ListNode* pNode)
     25 {
     26     if(pNode == NULL)
     27             printf("The node is NULL
    ");
     28     else
     29             printf("The key in node is %d.
    ", pNode->m_nValue);
     30 }
     31 
     32 //输出链表 
     33 void PrintList(ListNode* pHead)
     34 {
     35     ListNode *pNode = pHead;
     36     while(pNode != NULL)
     37     {
     38         cout << pNode->m_nValue<< " ";
     39         pNode = pNode->m_pNext;
     40     }
     41     cout<<endl;
     42 }
     43 
     44 //删除结点 
     45 void DestroyList(ListNode* pHead)
     46 {
     47     ListNode* pNode = pHead;
     48     while(pNode != NULL)
     49     {
     50         pHead = pHead->m_pNext;
     51         delete pNode;
     52         pNode = pHead;
     53     }
     54 }
     55 
     56 //往链表末尾添加结点
     57 /*
     58 注意这里pHead是一个指向指针的指针,在主函数中一般传递的是引用。
     59 因为如果要为链表添加结点,那么就会修改链表结构,所以必须传递引用才能够保存修改后的结构。
     60 */
     61 void AddToTail(ListNode** pHead, int value)
     62 {
     63     ListNode* pNew = new ListNode();
     64     pNew->m_nValue = value;
     65     pNew->m_pNext = NULL;
     66 
     67     if(*pHead == NULL)
     68     {
     69         *pHead = pNew;
     70     }
     71     else
     72     {
     73         ListNode* pNode = *pHead;
     74         while(pNode->m_pNext != NULL)
     75             pNode = pNode->m_pNext;
     76 
     77         pNode->m_pNext = pNew;
     78     }
     79 }
     80 
     81 
     82 //链接两个结点 
     83 //void ConnectListNodes(ListNode* pCurrent, ListNode* pNext)
     84 //{
     85 //    if(pCurrent == NULL)
     86 //    {
     87 //        printf("Error to connect two nodes.
    ");
     88 //        exit(1);
     89 //    }
     90 //    pCurrent->m_pNext = pNext;
     91 //}
     92 
     93 //防御性编程,鲁棒性更好
     94 ListNode* FindKthToTail(ListNode* pListHead, unsigned int k)
     95 {
     96     if(pListHead == NULL || k == 0)
     97             return NULL;
     98 
     99     ListNode *pAhead = pListHead;
    100     ListNode *pBehind = NULL;
    101 
    102     for(unsigned int i = 0 ; i < k- 1 ; i ++)
    103     {
    104         if(pAhead->m_pNext != NULL)
    105             pAhead = pAhead->m_pNext;
    106         else
    107             return NULL;
    108     }
    109     
    110     pBehind = pListHead;
    111     while(pAhead->m_pNext != NULL)
    112     {
    113         pAhead = pAhead->m_pNext;
    114         pBehind = pBehind->m_pNext;
    115     }
    116 
    117     return pBehind;
    118 }
    119 
    120 int main()
    121 {
    122     //创建结点
    123     ListNode* pNode1=CreateListNode(1);//创建一个结点
    124     PrintList(pNode1);//打印
    125     //往链表中添加新结点
    126     AddToTail(&pNode1, 2);//为链表添加一个结点
    127     AddToTail(&pNode1, 3);//为链表添加一个结点
    128     AddToTail(&pNode1, 4);//为链表添加一个结点
    129     AddToTail(&pNode1, 5);//为链表添加一个结点
    130     AddToTail(&pNode1, 6);//为链表添加一个结点
    131     AddToTail(&pNode1, 7);//为链表添加一个结点
    132     //打印链表
    133     PrintList(pNode1);//打印
    134     //反转链表
    135     ListNode* KthNode=FindKthToTail(pNode1,3);
    136 
    137     PrintListNode(KthNode);
    138 
    139     DestroyList(pNode1);
    140     
    141     return 0;
    142 }

  • 相关阅读:
    异构数据库同步工具调研
    ubuntu16.04 Golang语言开发环境搭建
    串口USB单一映射及重命名
    linux arm 交叉编译ACE(ubuntu16.04)
    ubuntu16.04 下Mongo数据库搭建
    ubuntu 增加一个用户 并赋予权限
    go 通过http发送图片file内容
    git 简单命令总结
    gitlab ssh_key
    ubuntu16.04 程序开机自启动设置及启动优化
  • 原文地址:https://www.cnblogs.com/sankexin/p/5616328.html
Copyright © 2011-2022 走看看