删除单链表的倒数第m个元素

转载 2006年05月21日 09:08:00

[题目]:    给定一个单向链表(长度未知),请设计一个既节省时间又节省空间的算法来找出该链表中的倒数第m个元素。实现这个算法,并为可能出现的特例情况安排好处理措施。“倒数第m个元素”是这样规定的:当m=0时,链表的最后一个元素将被返回。
   
    如果沿从头至尾的方向从链表中的某个元素开始,遍历m个元素后刚好达到链表尾,那么该元素就是我们所要找的。这样,我们可以引出第一种办法:从头结点开始,依次对链表的每一个元素进行这样的测试,遍历m个元素,看是否到达链表尾。直到我们找到那个倒数第m个元素为止。很明显,这个方案的效率是很差的,因为我们将对同一批元素进行反复多次的遍历。仔细研究一下这个方案就会发现,对于链表中的大部分元素,我们都要遍历m个元素;如果这个链表的长度为n,这个算法的执行时间大概是O(mn)级的。我们应该尝试寻找一个优于O(mn)级的解决方案。


    如果我们首先遍历该链表,统计链表的长度(假定为n),那么要找的元素在该链表中的位置即n-m。这样,从链表的头开始,向后遍历n-m个元素即可。虽说整个过程需要对链表进行2次遍历,但它仍然是一个O(n)级的算法,而且它只需要很少的几个临时变量。相对于此前的方案,这一思路的时间和空间效率有了显著的改进。要是你能设法省下统计链表长度的那一次遍历,这个算法将更加有效了。


    首先不妨假设在前2种算法中我们用指针p1遍历链表。p1指向链表尾的时候,我们所要找的元素(假定为data-m)跟链表尾的相对距离为m。如果这时候有另外一个指针p2指向data-m,也就是说,p1与p2间隔m个元素。如果把该单向链表改为双向链表,并保持p1、p2之间的同步,当p2指针回溯到链表头结点的时候,p1指针刚好指向从头结点开始的第m个元素。根据这个相隔m个位置的相对距离,我们完全可以明确地再设置一个用来遍历单向链表的指针p2,让它与链表的第一个指针p1(前2种算法中用于统计链表长度的指针)间隔m个元素,然后让它们同步前进。当p1指向链表尾时,p2刚好指向倒数第m个元素。
    那么怎样才能让这2个指针保持正确的m间距呢?我们可以这样做:当p1从链表头开始统计链表元素个数(注意要从0开始计算),等数到第m个元素时,再让p2指针从链表头开始出发。这个,他们之间的距离就是m个元素了。
    在这一过程中,如果链表的长度不足m个元素,我们在试图使p1前进m个元素时,很可能就会在半路上遇见对“NULL”指针进行操作的情况。因此,我们需要在这2个指针的出发阶段检查p1指针是否已经到达了链表的尾端。

算法描述: element *FindMToLastElement (int head,int m)
                      {
                          element *p1,*p2;
                          int i;
                          p1 = head;
                          for(i=0;i<m;i++)
                              { 
                               if(p1->next)
                               p1 = p1->next;
                              else
                              return NULL;
                              }
                         p2 = head;
                         while(p1->next)
                           {
                            p1 = p1->next;
                            p2 = p2->next;
                           }
                        return p2;
                      }

            
C++实现:

/*show_MToLast_node.cpp     Amirural设计 */
#include <iostream.h>

class ListNode
{
private:
 int data;
 ListNode *next_node;
 static ListNode *now;                                                 //目前的结尾结点指针
 const static ListNode *head;                                    //连接链表的起始指针,head ->next_node指向第一个结点

public:
 ListNode(int node_data):data(node_data),next_node(NULL){}
 ListNode():next_node(NULL)
 {head=now=this;}
 static void add_node(int new_data);                      //增加新的结点
 static void show_all_node();                                   //显示所有的结点          
 static void show_MToLast_node(int m);              //显示倒数第m个结点
};

ListNode *ListNode::now;           
const ListNode *ListNode::head;

void ListNode::add_node(int new_data)
{
 now->next_node=new ListNode(new_data);
 now=now->next_node;
}

void ListNode::show_all_node()
{
 now=head->next_node;
 while(now!=NULL)
 {
 cout<<now->data;
 if(now->next_node!=NULL)
  cout<<"->";
 now=now->next_node;
 }
}

void ListNode::show_MToLast_node(int m)
{
        ListNode *index,*mBehind;
        int i;
        index = head->next_node;
        for(i=0;i<m;i++)
         { 
         if(index->next_node)
          index = index->next_node;
        }

        mBehind = head->next_node;
        while(index->next_node)
        {
          index = index->next_node;
          mBehind = mBehind->next_node;
        }
        cout<<"The m to last data is:"<<mBehind->data<<endl;
 }

void main()
{
 int data,m;
 char choice;
 ListNode startnode;               

 do{
  cout<<"Please input data:";
  cin>>data;

  startnode.add_node(data);  
       
  cout<<"Do you want to input another data?";
  cin>>choice;
 }while(choice=='y'||choice=='Y');

 ListNode::show_all_node();

 cout<<"/nPlease input m:";
 cin>>m;
 ListNode::show_MToLast_node(m);
}

相关文章推荐

取单链表倒数第k个元素

  • 2011年12月07日 11:57
  • 7KB
  • 下载

Chapter 2 | Linked Lists--返回单链表倒数第n个元素及删除中间的某个节点

2.2    Implement an algorithm to find the nth to last element of a singly linked list. 译文:实现一个算法返回单链...

CareerCup之2.2 寻找单链表倒数第n个元素

【题目】 原文: 2.2 Implement an algorithm to find the nth to last element of a singly linked list. 译文:...

查找单链表的倒数第K个元素

算法思想:设置双指针,p1和p2,先让p1指针从头开始遍历k-1个节点,然后让p1继续遍历,p2从头遍历(p1和p2同时遍历),当p1遍历到链表的末尾,此时p2指针所指向的正好是倒数第k个节点。 如...

单链表查找倒数第k个元素

数据结构期末复习的时候遇到的这题,由于看过小甲鱼老师的数据结构视频,首先想到的想法是快慢指针(这里说双指针也许更合适),即第一个指针从头遍历到第k-1个元素时第二个指针从头开始遍历,第一个指针指向结尾...
  • jpcpj
  • jpcpj
  • 2016年07月09日 10:59
  • 157

[算法]找出单链表中的倒数第k个元素

找出单链表中的倒数第k个元素解题思路: 为了求出链表中的倒数第k个元素,最容易想到的方法是首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第k个,转换为正数第n-k个,接下去遍历一次就可以得...

如何找出单链表中的倒数第k个元素-----思路分析

题目:给出无环单链表头指针,找出单链表中的倒数第k个元素。 思路一:         初看题目,最容易想到的方法就是遍历。首先遍历一遍单链表,得出整个链表的长度n(元素个数从1到n),然后找...

一次遍历找出单链表中的倒数第k个元素

由于单链表只能从头到尾依次访问链表的各个节点,所以如果要找链表的倒数第k个元素,也只能从头到尾遍历查找。在查找过程中,设置两个指针,让其中一个指针比另一个指针先移动k步,然后两个指针同时往前移动。循环...

cc150:实现一个算法从一个单链表中返回倒数第n个元素

实现一个算法从一个单链表中返回倒数第n个元素。 解答 这道题的考点在于我们怎么在一个单链表中找到倒数第n个元素? 由于是单链表,所以我们 没办法从最后一个元素数起,然后数n个得到...

如何找出单链表中的倒数第k个元素

此题可谓是寻找单链表中间结点加强版。 为了找出单链表中的倒数第k个元素,最容易想到的方法是首先遍历一遍单链表,求出整个单链表的长度n,然后将倒数第k个,转换为正数第n - k个,接下去遍历一次就...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:删除单链表的倒数第m个元素
举报原因:
原因补充:

(最多只允许输入30个字)