2012-02-08 3 views
2

私はリンクリストを分割するCプログラムを持っています。これはロジックです - リンクリストに偶数のノードがある場合は、それを同じ半分に分割します。そうでなければ、1つのノードが子リンクリストよりも多い親リンクリストとそれを分割する。 以下のコードを実行すると、メインループのdisplay_LL関数が 'p'リンクリストを正しく表示します。その分割は正しく行われます。しかし、display_LL関数は、 'r'リンクリストのNULLを出力します。分割されたリンクされたリストが関数スコープの外で空になっています

'frontbacksplit_LL'関数の中からリンクリストを印刷すると、 'p'と 'r'のリンクリストが正しく表示されます。

なぜこのような別の動作、私は理解できません。

これはスコープの問題ですか?もしそうなら、私はコードにどのような変更を加える必要がありますか?

Plsはリンクリストと仮定します。 'p'は空のリンクリストではありません。ノードがあります。わかりやすくするためにコードを省略しました。また、display_LL関数コードも表示されません。

struct node { 
    int data; 
struct node *link; 
}; 

void main() 
{ 
    struct node *p,*q,*r; 

    p=NULL; 
    q=NULL; 
    frontbacksplit_LL(p,r,count(p)); //Imagine p has nodes. count(p) gives number of 
    printf("Front_Back Splits:\n"); //nodes in the linked list. 
    display_LL(p); //displays split linked list correctly 
    display_LL(r); //Shows EMPTY linked list. 
    getch(); 
} 

frontbacksplit_LL(struct node *a,struct node *b,int node_count) 
{ 
    struct node *temp; 
    int i,t; 
    temp=a; 

    if(node_count%2==0) //even 
    { 
     for(i=0;i<node_count/2;i++) 
      temp=temp->link; 
     b=temp->link; 
     temp->link=NULL; 
    } 
    else 
    { 

     for(i=0;i<(ceil(node_count/2));i++) 
      temp=temp->link; 
     b=temp->link; 
     temp->link=NULL; 
    } 
    display_LL(a); //Displays split linked list correctly. 
    display_LL(b); //Displays split linked list correctly. 
} 
+0

引数として渡されるポインタの変更:http://agnelkurian.com/blog/?p=168 –

+0

あなたの助けに感謝します。あなたの提案はすべて同じように有効です。しかし、コードを少し微調整すれば動作することがわかりました。私がしたことは、次のようなrへの参照を送りました:frontbacksplit_LL(struct node * a、struct node ** b、int node_count) そしてこれをfrontbacksplit_LL(p、&r、count(p)); に機能とボイラーが機能しました!親リンクリスト(私が観察したもの)の参照を送る必要はありません。 これに関するコメント? – bijeshn

+0

親リストポインタを変更していません。だから、参照することでそれを渡す必要はありません。 –

答えて

1

ポインタ変数prが機能frontbacksplit_LLに値によって渡されるためです。その結果、関数frontbacksplit_LL内で行われた変更は、(コピーを変更すると)関数のローカルになります。その後、

frontbacksplit_LL(struct node **a, struct node **b, int node_count) { 

とアクセス:として

あなたが機能frontbacksplit_LLに変数abに加えられた変更は、変数pmainqに反映取得したいので、あなたがアドレスでpqを渡す必要があります実際のポインタは*a*bです。それはあなたの既存のコードにあるa*abと置き換えて、*bと置き換えます。

としてそれを呼び出す:

frontbacksplit_LL(&p, &r, count(p)); 
1

あなたの問題は、あなたがた値によってポインタpqを渡すことです。したがって、内部で変更すると、frontbacksplit_LLこれらの変更は機能の外には表示されません。もちろん

frontbacksplit_LL(struct node **a,struct node **b,int node_count) 

のように、あなたは*a*bで機能コードのすべてのabを交換する必要があり、かなり値によってポインタでポインタを渡す必要があります。

1

問題はここにある:

struct node *p,*q,*r; 
frontbacksplit_LL(p, r, count(p)); 

右のそれを行うためには、あなたは後半へのポインタへのポインタとしてr宣言する必要があります。コードrが値渡しされるので、結果はローカル変数bfrontbacksplit_LLに格納されます。 r(つまり&r)のアドレスを渡すと正しく行われます。

関数宣言は次のようになります

frontbacksplit_LL(struct node** a, struct node** b, int node_count) 

、すべてa sおよびb sはそれぞれ*a*bに置き換えなければなりません。あなたは*p*rを通じてリストにアクセスする必要があると思います。この場合

struct node *p = NULL, *q = NULL, *r; 
frontbacksplit_LL(&p, &r, count(p)); 

または

struct node **p = NULL, *q = NULL, **r; 
frontbacksplit_LL(p, r, count(p)); 

として、あなたはそれを呼び出す必要があります。

1
struct llist { 
     struct llist *next; 
     char *payload; 
     }; 

struct llist *llist_split(struct llist **hnd); 

struct llist *llist_split(struct llist **hnd) 
{ 
struct llist *this, *save, **tail; 
unsigned iter=0; 

for (save=NULL, tail = &save; this = *hnd;) { 
     if (!this->next) break; 
     if (++iter & 1) { hnd = &this->next; continue; } 
     *tail = this; 
     *hnd = this->next; 
     tail = &(*tail)->next; 
     *tail = NULL; 
     } 
return save; 
} 

BTW:main()はintを返す必要があります。

関連する問題