0

リストの最後に要素を挿入して、その中の1つを表示できるプログラムを書いています。正しく挿入されますが、指定されたものを表示できます。

typedef struct Node
{
        int data;
        struct Node *next;
        struct Node *prev;
} node;

void insert(node *head, int data)
{
        node *newNode = (node*) malloc(sizeof(node));
        newNode->data = data;
        newNode->next = NULL;

        if(head == NULL)
        {
            head = newNode;
        }
        else
        {
            while(head != NULL)
                head = head->next;

            head->next = newNode;
            (head->next)->prev = head;
        }
}

void print(node *head, int element)
{
    node *temp = head;
    int count = 0, i = 1;
    while(i < element)
    {
        temp = temp->next;
        i++;
    }
    printf("%d", temp->data);
}

int main()
{
        node *start = (node*) malloc(sizeof(node));
        start = NULL;

        int data1 = 4, data2 = 5;
        insert(start,data1);
        insert(start,data2);

        print(start, 1);
}

なぜそれが機能しないのですか?また、私がこれを適切に行っているかどうか教えていただけますか?

4

3 に答える 3

1

startこれは、ポインタを値で渡すためです。これはinsert、関数が戻ると、関数内での変更が失われることを意味します。

参照によってポインタを渡すことができます。

void insert(node **head, int data)
{
    /* ... */
    if (*head == NULL)
        *head = newNode;
    else
    {
        /* ... */
    }
}

int main(void)
{
    node *start = NULL;
    insert(&start, 1);
    /* ... */
}

または、関数からポインタを返します。

node *insert(node *head, int data)
{
    /* ... */
    return head;
}

int main(void)
{
    node *start = NULL;
    start = insert(start, 1);
    insert(start, 2);  /* Do not get the returned pointer, as the returned pointer no longer points to the start of the list */
    /* ... */
}

これらの両方の解決策の問題は、headそうでない場合NULLは、最後のノードの前のノードを指すように変更することです。内部のループでinsertは、代わりに一時ポインターを使用する必要があります。


NULL安全上の予防措置として、関数のループにノードがないことを確認する必要がありprintます。リスト内のノードの数よりも大きい数を渡すと、そうでない場合はどうなるかを考えてください。

于 2013-01-19T17:08:55.037 に答える
0

編集:数行スキップしました。

のコード スニペットとインラインの私の修正されたコメントを参照してくださいmain()

node *start = (node*) malloc(sizeof(node));//You allocate memory here. Good.
start = NULL;//Memory leak. 

//Instead of the above two lines use this
node* start=NULL;

int data1 = 4, data2 = 5;
start=insert(start,data1);//If you want to do it statically, why not write insert(start,4)?
insert(start,data2);
....

関数に NULL チェックを追加することをお勧めしprint()ます。

void print(node *head, int element)
{
    //Null check for the start pointer.
    //If you would have had this here, you'd have never faced such problem.
    if(head == NULL)
    {
      //Handle null
    }
    node *temp = head;
    int count = 0, i = 1;
  ....
}

そして、あなたに追加することをおinsert()勧めします:

node* insert(node *head, int data)
{
        node *newNode = (node*) malloc(sizeof(node));
        newNode->data = data;
        newNode->next = NULL;

        if(head == NULL)
        {
            head = newNode;
            return head;
        }
        else
        {
            while(head != NULL)
                head = head->next;

            head->next = newNode;
            (head->next)->prev = head;
            return NULL;
        }
}

それが役に立てば幸い。

于 2013-01-19T17:15:55.347 に答える
0

物事をずっと簡単にし、コードをより効率的にするトリックがあります!

秘訣は、循環リストを使用し、「ヘッド」ノードをセンチネル値にすることです。prev空のリストは、自分自身をnext指している との両方を持つ単一のノードによって表されます。NULL は必要ありません。このスタイルにより、必要な特殊なケースが大幅に削減されます。また、リストの先頭と末尾の両方に O(1) アクセスできます。headのdataフィールドは使用されません。これについては、Knuth の「The Art of Computer Programming」で説明されています。

このスタイルでは、次のようなものが得られます: [未テスト]

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

typedef struct Node {
   int data;
   struct Node *next, *prev;
} node;

void insert_list(node *head, int data) {
  node d = {data, head, head->prev};
  node *new_node = malloc(sizeof(node));
  /* TODO: handle malloc failure */
  *new_node = d;
  head->prev->next = new_node;
  head->prev = new_node;
}

node *get_list(node *head, int n) {
  node *node = head;
  int i;
  for (i = 0; i <= n; i++) {
    node = node->next;
    if (node == head) {
      /* TODO: handle out-of-bounds index */
    }
  }
  return node;
}

void print_list(node *head, int i) {
   printf("%d\n", get_list(head, i)->data);
}

node *new_list(void) {
  node *head = malloc(sizeof(node));
  /* TODO: handle malloc failure */
  head->next = head->prev = head;
  return head;
}

int main(int argc, char**argv) {
  node *list = new_list();
  insert_list(list, 10);
  insert_list(list, 20);
  print_list(list, 0);
  print_list(list, 1);
  return 0;
}
于 2013-01-19T18:38:33.077 に答える