链表中倒数第k个结点

Posted yutingliuyl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了链表中倒数第k个结点相关的知识,希望对你有一定的参考价值。

【题目】
输入一个链表,输出该链表中倒数第k个结点。


【分析】
对于此题。考虑单链表实现,单链表仅仅能从头到尾遍历,而要找到倒数第k个结点,就须要确定,正数是第几个结点,假设结点总数为n。最后一个结点位置为n-1,而倒数第k个结点的位置就为n-k+1。假设从头节点開始遍历,仅仅要遍历到n-k+1步就能够。这就意味着我们须要知道两个关键信息,一个是链表长度,一个就是n-k+1。这就须要遍历两次。非常明显,这不是最佳方案。比較好的方法就是一次遍历就能够找到,假设我们用两个指针,当一个指针指向n,还有一个指针和他相距k-1个时。还有一个指针所指向的位置就是n-k+1的位置。就是我们要找的位置,利用两个间距为k-1的指针实现此题不失为一种有效的办法。


【測试代码】

#include<stdio.h>
#include<stdlib.h>
#include<stack>

typedef int data_type;

typedef struct Node node_t;// 给struct Node取个别名node_t
typedef struct Node * node_ptr;//给struct Node*取个别名node_ptr

typedef struct Node
{
    data_type data;
    struct Node *node_next;//node_next是一个指向结构的指针,告诉指针要指向的地址就要付给它一个结构类型地址
};

//链表初始化
node_t * init()
{
    node_ptr p;
    p = (node_t *)malloc(sizeof(node_t));
    p->node_next = NULL;
    return p;
}
//在链表后面插入结点
node_t *insert_back(node_ptr p , data_type data)
{


    node_ptr pnew = (node_t *)malloc(sizeof(node_t));
    pnew ->node_next = NULL;
    pnew ->data = data;

    p->node_next = pnew;

    return pnew;
}

node_t * find(node_ptr p, unsigned int k)
{
  if(p == NULL || k == 0)
      return NULL;
  node_ptr pAhead = p;
   node_ptr   pBehind =NULL;
  for( int i = 0 ; i<k-1; i++)
  {
      if(pAhead->node_next != NULL)
            pAhead = pAhead->node_next;
      else
          return NULL;
  }
  pBehind = p;
  while(pAhead->node_next != NULL)
  {
      pAhead = pAhead->node_next;
      pBehind = pBehind->node_next;
  }

  return pBehind;



}
//正常打印
void print(node_ptr p)
{
    if(!p)
    {
            printf("no data, you think too much");
            return ;
    }

    while(p->node_next != NULL)
    {
        printf("%d ", p->data);
        p = p->node_next;
    }
    printf("%d ", p->data);
    printf("\n");

}



void main()
{
    node_ptr pnode, list;
    pnode = init();
    list = pnode;

    pnode = insert_back(pnode, 1);
    pnode = insert_back(pnode, 2);
    pnode = insert_back(pnode, 3);
    pnode = insert_back(pnode, 4);
    pnode = insert_back(pnode, 5);
    pnode = insert_back(pnode, 6);

    node_t *target =  find(list, 3);
    int find_data = target->data;
    printf("倒数第3个数是:%d\n",find_data);

}

这里一定要注意一些特殊条件。假设单链表是空的,查找的位置设定为0,结点总数小于k。这些都是要考虑的,否则一旦出现这样的測试问题。整个程序都会崩溃,小漏洞是能够使整个功亏一篑的。


【输出】
技术分享


【延伸】
这个题解题思路能够延伸到其它须要遍历測试的,比方说測试一个单链表是不是回环。设置两个指针。一个指针一次一步。还有一个一次两步。到最后假设快的指针居然追上了慢的那个就说明,是回环。假设走得快的走到了链表的末尾还是没有追上慢的说明,不是回环;还有測试单链表的中间结点,设置两个指针。一个走一步。还有一个走两步。走两步的走到末尾时,走得慢的就走到了中间节点处,由于快的指针是慢的2倍,快的走到了n-1位置。慢的位置就是(n-1)/2,这样的一个指针不能一次性遍历解决这个问题的就用两个指针。





以上是关于链表中倒数第k个结点的主要内容,如果未能解决你的问题,请参考以下文章

剑指 14. 代码的鲁棒性链表中倒数第k个结点

链表中倒数第k个结点

高质量代码-链表中倒数第k个结点

剑指offer:链表中倒数第k个结点

链表中倒数第k个结点-剑指Offer

链表中倒数第k个结点