2012-01-28 2 views
1

これは私にとって初心者で、単なるリンクリストで練習しています...しかし、どこかで私は物事を混乱させる必要があります。私のコードはかなりまっすぐ進む..あなたが期待するBool関数は常に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"; 

} 

答えて

0

。(私はテール・ノードを削除し、今ちょうどメモリのいくつかのランダムな部分を指し示す前の1のリンクです?問題?そして、なぜ無限ループということですか?

はそれのように見える:あなたが削除されたpの指す

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を指し悪いそれはこのようなものでなければなりません:。。

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; 
} 

基本例1におけるhead==NULLhead->link == NULL場合はすでに、P-するので、最初の呼び出しをチェックしましたので、これはリンク - >(と仮定すると、メモリは他の理由で破損していない)を実行しても安全です> link = head-> link-> linkはあなたに不適切なポインタアクセスを与えません。 head-> link-> link == NULLの場合はOKです。


そして、なぜ無限ループ?

興味深い質問です。

多少の間違った哲学的説明があります:悪いポインタにアクセスしたことによって引き起こされた不正なメモリアクセスエラーがないと仮定すると、どこかをランダムに指し示すポインタ値について話しています。実際のメモリは有限であるため、有限集合内のポインタ参照の任意のシーケンスは、サイクルのある時点で繰り返さなければならない(さもなければ集合は有限ではない)。もちろん、無限ループを止めるNULLを含めることができます。

0xcdcdcdcdを指し示す0xcdcdcdcdのような、OSメモリマネージャによって予約されたいくつかの不良メモリパターンを打つ可能性が高いでしょう。この場合、それは悪い選択です:デフォルトのメモリパターンは、おそらくポインタに表示された場合、メモリの例外が無効になるように設計する必要があります。

デバッガでプログラムを停止し、ポインタの値が何であるかを教えてください。それは質問のその部分に答えることができます。

+0

絶対に正しいジェイソン入力のおかげで!私はそれを見つけ出し、あなたの時間を節約するために私のポストを編集しましたが、あなたが速すぎるように見えます:) –

+0

しかし、私のブール関数はまだ動作していません.... –

+0

それは今うまく動いています.. :) –

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=NULL;付き)の引数の値を更新することを意図しているときに、ローカル変数headNode* head=NULL;付き)機能removetailで宣言したことを指摘しています。

found(アドレス)が常に真である理由を2番目のエラーで説明します。あなたはおそらく関数をfound(...)と呼ぶことを意図していました。

+0

ok fixed all問題点!警告については、これは私がまだ得ているものです: 警告W8004 10.cpp 72: 'q'には、関数では一度も使用されない値が割り当てられます。 addtail(ノード*&、int) 警告W8004 10.cpp 100 : 'p'には機能で使用されない値が割り当てられます removehead(Node *&) 警告W8004 10.cpp 130: 'q'には機能で使用されない値が割り当てられます removetail(Node *&) 警告W8004 10.cpp 126: 'p'には決して関数で使用されない値が割り当てられます removetail(Node *&) –

+0

未使用の値についての警告はなぜ使用していますか? –

0

まず最初に、あなたはおそらく、関数ポインタ、すなわちそれことを、nullではない「が見つかり」する場合は、最初のバージョンは基本的にチェックしている

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

でなければなりません

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

を行うということです値があります。 2番目の関数は実際に必要と思われる関数を実際に呼び出します。

もう1つは、テールを外すときです。あなたは実際にそれをリストから削除しているわけではなく、単に削除しているだけです。リストからもリンクを解除する必要があります。そうしないと、初期化されていないメモリをポイントします。

+0

Joachim、私もあなたの2番目のバージョンを試しました(実際に私が最初に使ったバージョンです)が、出力では常に "見つかった"ということになります!何か他の問題でなければならない! –

+0

非常に奇妙な、私は正しい結果を得る(removableetailを固定した後) –

+0

同様にブールを修正した.. :) –