Bool功能始终如一&单链接列表中的尾节点移除会产生无限循环

时间:2012-01-28 11:47:42

标签: c++ boolean singly-linked-list

好吧,这是我在单链表上的训练,是一个新手...但是,在某个地方,我一定是搞乱了。我的代码很简单,包含了您期望的所有典型程序。

问题:

即使我输入不在列表中的数字

,我的布尔函数也始终为true

这是我的代码,看看主要功能,以了解事情发生的顺序。哦,谢谢你的帮助!! :)

#include <string>
#include <iostream>

using namespace std;

class Node
{
    public:
         int n;
         Node* link;
};

void display(Node* head)
{

    cout<<head->n<<" ";

    while(head->link!=NULL)
    {
        head=head->link;
        cout<<head->n<<" ";
    }
    cout<<endl;

}

void addnode(Node*& head, int x) 
{
    if(head==NULL)
    {
        head=new Node;
        head->n=x;
        head->link=NULL; // Necessary? Why?
    }

    else
    {
        Node* p=new Node;
        p->n=x;
        p->link=head;
        head=p;
    }
}

bool found(Node* head, int x)
{                            
    if(head->n==x) return true;

    while(head->link!=NULL)
    {
        head=head->link;
        if(head->n==x) return true;
    }

    return false;
}


void addtail(Node*& head, int x) 
{                                
    if(head==NULL)          
    {                        
        head=new Node;  
        head->n=x;
        head->link=NULL;
    }

    else
    {
        Node* q=NULL; 
        q=head;       
        while(q->link!=NULL) q=q->link;

        Node* r=new Node;
        r->n=x;
        r->link=NULL;
        q->link=r;
    }
}

int removehead(Node*& head) 
{
    if(head==NULL)
    {
        cout<<"The list is empty";
        return 0; 
    }             

    int x;

    if(head->link==NULL)
    {
        x=head->n;
        head=NULL;
        return x;%0stackoverflow.com 
    Node* p=NULL;    
    p=head;
    head=head->link;
    x=p->n;
    delete p;
    return x;
}

int removetail(Node*& head) 
{
    if(head==NULL)
    {
        cout<<"The list is empty";
        return 0;
    }

    int x;

    if(head->link==NULL)
    {
        x=head->n;
        delete head;
        Node* head=NULL;
        return x;
    }

    Node* p=NULL; 
    p=head;
    while(p->link!=NULL) p=p->link;

    x=p->n;
    delete p;
    return x;
}



int main()
{

    int y; int z;

    Node* p=NULL;

    while(cin>>y)
    {
        addnode(p,y);
    }

    cin.clear(); cin.ignore(); 


    cout<<endl;

    display(p);

    cout<<endl;

    cout<<removehead(p)<<" ";

    cout<<removetail(p)<<endl;

    display(p);

    cout<<endl<<"give me a number:";

    cin>>z;

    if(found) cout<<endl<<"found"; 

    else cout<<endl<<"not found";

}

3 个答案:

答案 0 :(得分:0)

  

。(当我删除尾节点时,前一个节点的链接现在只是指向内存的一些随机部分?这是问题吗?为什么无限循环?

看起来像:

int removetail(Node*& head) 
{
    // base cases elided

    Node* p=NULL; 
    p=head;
    while(p->link!=NULL) p=p->link;

    x=p->n;
    delete p;
    return x;
}

指向您要删除的p的上一个链接仍然指向p。坏。它应该是这样的:

int removetail(Node*& head) 
{
    // base cases elided

    Node* p=NULL; 
    p=head;
    while(p->link->link!=NULL) p=p->link;

    x=p->link->n;
    delete p->link;
    p->link = NULL;     // maintain linked list integrity
    return x;
}

这样做是安全的(假设内存没有因其他原因而损坏),因为您已经在其中一个基本案例中检查了head==NULLhead->link == NULL,因此初次调用p - &gt; link-&gt; link = head-&gt; link-&gt;链接不会给您任何不正确的指针访问权限。如果head-&gt; link-&gt; link == NULL,那没关系。


  

为什么无限循环?

一个有趣的问题。

对于一个稍微有缺陷的哲学解释:假设您没有因访问错误指针而导致非法内存访问错误,那么您正在谈论随机指向某处的指针值。实存储器是有限的,因此有限集中的任何指针引用序列都必须在一个周期中的某个点重复(否则该集合将不是有限的)。当然,这可能包括一个可以阻止无限循环的NULL。

你更有可能遇到OS内存管理器保留的一些坏内存模式,比如指向0xcdcdcdcd的0xcdcdcdcd。在这种情况下,这是一个糟糕的选择:默认的内存模式应该设计成如果它们出现在指针中,它们可能会导致错误的内存异常。

您可以在调试器中停止程序并告诉我们指针值是什么,这将回答问题的这一部分。

答案 1 :(得分:0)

编译时应该打开警告。以下是编译器所说的内容:

% g++ -Wall list.cc
list.cc: In function ‘int removetail(Node*&)’:
list.cc:120:15: warning: unused variable ‘head’ [-Wunused-variable]
list.cc: In function ‘int main()’:
list.cc:166:13: warning: the address of ‘bool found(Node*, int)’ will always evaluate as ‘true’ [-Waddress]

第一个错误指出你在函数head中声明了一个局部变量removetail(带有Node* head=NULL;),而你可能想要更新参数的值(仅{{1} }})。

第二个错误解释了为什么head=NULL;(地址)始终为真。你可能打算用一些参数调用函数found

答案 2 :(得分:0)

首先是你做了

if(found) cout<<endl<<"found"; 

应该是

if(found(p,z)) cout<<endl<<"found";

第一个版本基本上是检查“found”的函数指针是否为空,即它是否有值。第二个实际上调用了你可能想要的功能。

第二件事就是当你移除尾巴时。你实际上并没有从列表中删除它,你只是删除它。你需要取消它与列表的链接,否则你将指向未初始化的内存。