2017-02-20 12 views
0

Итак, я пытался убедиться, что я СОЛНЕЧНО понимаю связанные списки. Вот что у меня есть до сих пор:Связанный список Malloc() при вставке?

typedef struct node 
{ 
    int num; 
    struct node *next; 

}node; 

int main() 
{ 
    node *HEAD = create(5); 
    printf("Address:%p Value:%i\n", HEAD, HEAD->num); 
    HEAD = insert(HEAD,3); 
    printf("Address:%p Value:%i\n", HEAD, HEAD->num); 
    HEAD = insert(HEAD,7); 
    printf("Address:%p Value:%i\n", HEAD, HEAD->num); 
    return 0; 
} 

node* create(int value) 
{ 
    node *HEAD = malloc(sizeof(node)); 
    if(HEAD == NULL) 
    { 
     printf("Space Unable to be allocated for HEAD\n"); 
    } 
    HEAD->num = value; 
    HEAD->next = NULL; 
    return HEAD; 
} 

node* insert(struct node *HEAD,int value) 
{ 
    node *new_node = malloc(sizeof(node)); 
    new_node->num = value; 
    new_node->next = HEAD; 
    HEAD = new_node; 
    return HEAD; 
} 

void print(struct node *HEAD) 
{ 
    node *trav = HEAD; 
    while(trav != NULL) 
    { 
     printf("Value in Linked List:%i\n",trav->num); 
     trav = trav->next; 
    } 
} 

Так что это работает и печатает 5,3,7, как должно. Однако, вытаскивая его на бумаге, меня слегка смущает вид node *new_node = malloc(sizeof(node));. Так как мне кажется, что каждый раз при вставке мы создаем новый указатель под названием «new_node», который кажется, что много оставшихся указателей просто болтаются. Что будет иметь смысл, так это для new_node каждый раз менять каждый раз, чтобы указать пространство malloc'd для нового вставленного узла.

Так что я делаю что-то не так здесь, или когда я malloc что-то с тем же именем, это старый, который просто переписывается (если это имеет смысл?), Или я должен быть свободным() в new_node после его были вставлены каждый раз?

Благодаря

+0

Вы не вставляете новые значения, вы просто создаете новые узлы и печатаете их. Посмотрите, где вы «связываете» головной узел и вновь созданный узел. Вы не найдете его. –

+0

Локальные переменные внутри функции перестают существовать, как только они возвращаются. * И * «new_node каждый раз, когда указывать на пространство malloc'd для нового узла, который вставлен», уже происходит, что происходит! Попробуйте использовать отладчик, чтобы пройти через код по строкам и проверить переменные и их значения. Или просто распечатайте все (помните, что 'printf' использует' '% p" 'для печати' void * '(и да, вам нужно наложить указатели)). –

+0

Я бы предложил вам сначала использовать какой-то рабочий пример, чтобы понять, как написать свой собственный код. – tod

ответ

1

Нет, вы не должны освобождать new_node. Если вы это сделаете, то после того, как программа выйдет из функции , вставьте вашу переменную HEAD будет указывать на NULL.

Что происходит, каждый раз, когда вы используете malloc, для него выделяется некоторое пространство памяти. Поэтому в случае функции вставьте вашу переменную new_node указывает на нее, а затем вы делаете этот узел HEAD.

Теперь, когда программа выходит, что функция, new_node как переменная удаляется, но объем памяти, он указал на, в настоящее время, на который указывает РУКОВОДИТЕЛЯ и все созданные вами до этого момента узлы могут быть достигнуты путем перемещения HEAD. Поэтому вы остаетесь без оборванных указателей.

+0

Так ли мое решение правильно? потому что в основном все говорят, что я не делаю это правильно. Но, похоже, вы правы, я печатал & new_node после каждой вставки, и он остается прежним. Valgrind показывает, что у меня память заблокирована, поэтому я должен освобождаться от END программы, которую я бы предположил? – msmith1114

+0

@ msmith1114 Я не думаю, что с вашим кодом что-то не так. Вы можете написать код связанного списка любым способом. Например, здесь вы вставляете узел и делаете его _HEAD_, что делают многие люди, вставляйте узел в конец. См. Эту страницу для дальнейшего понимания. http://quiz.geeksforgeeks.org/linked-list-set-2-inserting-a-node/ – deepakgupta8777

3

Think связанному список как вагоны, каждый раз, когда вы добавляете новый автомобиль, вам необходимо подключить его к последней машине, или поезд не будет тянуть вновь добавленный узел.

Таким образом, псевдо-код должен быть таким:

main { 
    // create the locomotive 
    head = create_new_node(5); 
    // link new car 
    insert(head, 7); 
    // link new car 
    insert(head, 9); 
    // hit the road jack 
    dump(head); 
} 

Создание нового автомобиля

create_new_node(value) {  
    // get the resources for a new car 
    node *p = (node*)malloc(sizeof(node)); 
    // load the car 
    p->value = value; 
    // attach the car connector 
    p->next = null; 
    // get the new car on field 
    return *p; 
} 

Вставка в конце поезда

insert(head, val) { 
    node *p = head; 
    // go to the last train car 
    while(p->next != null) p = p->next; 
    // create new train car 
    node *n = create_new_node(val); 
    // link it to the last car 
    p->next = n; 
} 

осматривая поезд

dump(head) { 
    // i don't want the 'head' to be changed, so I use a reference instead. 
    node *p = head; 
    // loop each car + the locomotive until end is reached 
    while(*p != null) 
    { 
     // count the load 
     write p->value; 
     // inspect the next car 
     p = p->next; 
    } 
} 
+0

Я просто добавляю его спереди, что кажется таким же хорошим? Я не уверен, что вижу проблему с моей? Это позволяет избежать необходимости прохождения всего списка до конца, когда я могу просто вставить его в начале/ – msmith1114

+0

@ msmith1114 Не обязательно, вы также можете иметь указатель на конец списка и вставлять туда узлы, без необходимости проходить весь список. В связанных списках есть 'O (1)' insertion, что означает, что вы можете вставлять узлы в начале или конце списка. Вы должны взглянуть на структуры LIFO и FIFO. – RoadRunner

+0

@ msmith1114 Вы не добавляете его на передний план, вы теряете ссылки, когда вы устанавливаете 'head' в новое значение. Важно здесь, вы должны уметь читать все значения с заданным указателем на голову. –