Я составил список с двойной связью и несколько раз запускал его с функциями для добавления узлов в конце, вывода длины списка и вывода всех элементов.
Все работало нормально.
Затем я создал функцию для добавления узла в определенное место под названием AddNodeAt(). и с тех пор он больше не работает.
head продолжает устанавливаться на NULL.
После того, как AddNode() выполнено, другие функции работают так, как будто head указывает на NULL, а не на список.
Это полный код:
#include <stdio.h>
#include <stdlib.h>
struct node {
node *prev;
int val;
node *next;
};
typedef struct node node;
node *head;
node *AddNode(node *head, int value)
{
node *ptr = (node *)malloc(sizeof(node));
if (!ptr) {
printf("No Memory Available");
} else
if (!head) {
ptr->val = value;
ptr->next = NULL;
ptr->prev = NULL;
head = ptr;
} else {
node *temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = ptr;
ptr->prev = temp;
ptr->next = NULL;
ptr->val = value;
}
return head;
}
int ListLength(node *head)
{
int count = 0;
if (head == NULL) {
printf("\nEmpty List\n");
} else {
node *temp = head;
count = 1;
while (temp->next != NULL) {
temp = temp->next;
count++;
}
printf("\n%d nodes\n", count);
}
return count;
}
node *AddNodeAt(node *head, int position, int value)
{
int i = 0;
node *temp = head;
node *ptr = (node *)malloc(sizeof(node));
if (head == NULL && position != 1) {
printf("Empty Linklist, cannot insert node at the given position");
} else
if (position > ListLength(head) + 1) {
printf("list too short, cannot insert node at the given position");
} else
if (position == ListLength(head) + 1) {
while (temp->next) {
temp = temp->next;
}
temp->next = ptr;
ptr->next = NULL;
ptr->val = value;
ptr->prev = temp;
} else {
while (i < position) {
i++;
temp = temp->next;
}
ptr->next = temp->next;
temp->next = ptr;
ptr->prev = temp;
ptr->val = value;
temp = ptr->next;
temp->prev = ptr;
}
return head;
}
void PrintList(node *head)
{
node *temp = head;
if (!head) {
printf("list empty");
} else {
while (temp->next != NULL) {
printf("%d->", temp->val);
temp = temp->next;
}
printf("%d", temp->val);
}
}
int main() {
int value = 0;
int num = 0;
int position = 0;
printf("Number of nodes to be made: ");
scanf("%d", &num);
for (int i = 1; i <= num; i++) {
printf("value in node number %d: ", i);
scanf("%d", &value);
AddNode(head, value);
}
PrintList(head);
ListLength(head);
printf("\nPosition of new node: ");
scanf("%d", &position);
printf("\nNumber of nodes:");
scanf("%d", &value);
AddNodeAt(head, position, value);
PrintList(head);
ListLength(head);
return 0;
}
Любые рекомендации будут оценены по достоинству. Я попытался закомментировать разделы, которые добавил прямо перед тем, как возникла эта проблема.
Я ожидал, что другие начнут работать так же, как работали раньше, но этого не произошло. head продолжает устанавливаться на NULL.
AddNode и AddNodeAt возвращают возможно измененную head, поэтому main() следует присвоить возвращаемое значение из этих функций head. Альтернативно, функции можно переписать, чтобы использовать двойной указатель на head (node **head).
Ошибка №1: использование глобальной переменной. Не используйте глобальные переменные.
... или скомпилируйте с помощью Clang и опции «-Weverything»: clang -Weverything file.c, чтобы увидеть все возможные предупреждающие сообщения, включая «объявление затеняет переменную в глобальной области видимости».





Проблема в присвоении head=ptr в функции AddNode. Это изменит только локальную переменную head. Он не будет изменять глобальную переменную с тем же именем, эта глобальная переменная останется NULL.
Простое решение этой проблемы — использовать указатель, который возвращает AddNode:
head = AddNode(head,value);
У вас та же проблема с функцией AddNodeAt.
Кстати, не используйте глобальные переменные. Вы можете определить head локально внутри функции main.
Проблема была устранена, если сделать head локальной переменной в main и обновить ее с помощью возврата aAddNode(). Спасибо.
head не устанавливается в NULL: глобальная переменная head инициализируется значением NULL перед запуском программы и никогда не обновляется, чтобы указывать на выделенный список.
Вам следует создать head локальную переменную в main и обновить ее до возвращаемого значения функций AddNode и AddNodeAt.
Обратите внимание на другие проблемы:
scanf() и сообщайте об ошибках ввода.typedef перед определением struct node, чтобы node было доступно для определений членов. Как указано, ваш код не компилируется как C, но является допустимым C++.ListLength не должен ничего выводить. Используйте отдельные функции для вычисления длины списка и для печати длины списка.#include <stdio.h>
#include <stdlib.h>
typedef struct node node;
struct node {
node *prev;
int val;
node *next;
};
int get_integer(void) {
for (;;) {
int value;
int c;
switch (scanf("%d", &value)) {
case 1:
/* read and discard the rest of the input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("\n");
return value;
case EOF:
fprintf(stderr, "unexpected end of file, aborting\n");
exit(1);
default:
/* read and discard the rest of the input line */
while ((c = getchar()) != EOF && c != '\n')
continue;
fprintf(stderr, "invalid input, try again\n");
break;
}
}
}
node *AddNode(node *head, int value) {
node *ptr = (node *)malloc(sizeof(node));
if (!ptr) {
fprintf(stderr, "No Memory Available\n");
exit(1);
}
ptr->val = value;
ptr->next = NULL;
ptr->prev = NULL;
if (!head) {
head = ptr;
} else {
node *temp = head;
while (temp->next) {
temp = temp->next;
}
temp->next = ptr;
ptr->prev = temp;
}
return head;
}
int ListLength(const node *head) {
int count = 0;
while (head != NULL) {
count++;
head = head->next;
}
return count;
}
void PrintListLength(const node *head) {
if (head == NULL) {
printf("Empty List\n");
} else {
printf("%d nodes\n", ListLength(head));
}
}
node *AddNodeAt(node *head, int position, int value) {
if (position > ListLength(head) + 1) {
printf("list too short, cannot insert node at the given position\n");
return head;
}
node *ptr = (node *)malloc(sizeof(node));
if (!ptr) {
fprintf(stderr, "No Memory Available\n");
exit(1);
}
/* initialize the new node */
ptr->value = value;
ptr->next = NULL;
ptr->prev = NULL;
if (position <= 1) {
/* insert at front */
if (head) {
ptr->next = head;
head->prev = ptr;
}
head = ptr;
} else {
node *temp = head;
for (int i = 1; i < position; i++) {
temp = temp->next;
i++;
}
ptr->prev = temp;
temp->next = ptr;
ptr->next = temp->next;
if (ptr->next) {
ptr->next->prev = ptr;
}
}
return head;
}
void PrintList(const node *head) {
const node *temp = head;
if (!head) {
printf("list empty\n");
} else {
while (temp->next != NULL) {
printf("%d->", temp->val);
temp = temp->next;
}
printf("%d\n", temp->val);
}
}
void FreeList(node *head) {
while (head) {
node *next = head->next;
free(head);
head = next;
}
}
int main(void) {
int value = 0;
int num = 0;
int position = 0;
node *head = NULL;
printf("Number of nodes to be made: ");
num = get_integer();
for (int i = 1; i <= num; i++) {
printf("value in node number %d: ", i);
value = get_integer();
head = AddNode(head, value);
}
PrintList(head);
PrintListLength(head);
printf("Position of new node: ");
position = get_integer();
printf("Node value: ");
value = get_integer();
head = AddNodeAt(head, position, value);
PrintList(head);
PrintListLength(head);
FreeList(head);
return 0;
}
Я использую код VS. Я не уверен, есть ли у него отдельный компилятор для C++ и C, поскольку я новичок в программировании. Я просто проверяю, что расширение файла «.c».
Как написано AddNode неверно, или, по крайней мере, использовано неправильно. В main, как указано, AddNode вызывается дважды:
for (int i = 1; i <= num; i++)
{
printf("value in node nummber %d : ", i);
scanf("%d", &value);
AddNode(head, value);
}
PrintList(head);
ListLength(head);
printf("\nPosition of new node:");
scanf("%d", &position);
printf("\nNumber of node :");
scanf("%d", &value);
AddNodeAt(head, position, value);
И возвращаемое значение игнорируется. Если вы измените его на
for (int i = 1; i <= num; i++)
{
printf("value in node nummber %d : ", i);
scanf("%d", &value);
head = AddNode(head, value);
}
PrintList(head);
ListLength(head);
printf("\nPosition of new node:");
scanf("%d", &position);
printf("\nNumber of node :");
scanf("%d", &value);
head = AddNodeAt(head, position, value);
Это будет работать. Но есть и другие ошибки.
Также вам необходимо изменить
struct node
{
node* prev;
int val;
node* next;
};
к
struct node
{
struct node* prev;
int val;
struct node* next;
};
Чтобы скомпилировать это в C, или хотя бы поместите typedef перед объявлением struct, как
typedef struct node node;
struct node
{
node* prev;
int val;
node* next;
};
Не буду углубляться в ошибки. Вместо этого я предоставлю некоторое обсуждение и добавлю полный пример (и еще несколько обсуждений) в конце. Это длинный пост, и вы можете сразу перейти к TL;DR или просто проигнорировать все это...
AddNode()Внутри AddNodehead находится локальный node*, но чуть выше мы видим node как глобальную node* вещь. Совсем не хорошо. А в main возвращаемое значение просто игнорируется.
node* head;
node* AddNode(node* head, int value)
{
node* ptr = (node*)malloc(sizeof(node));
if (!ptr)
{
printf("No Memory Available");
}
else if (!head)
{
ptr->val = value;
ptr->next = NULL;
ptr->prev = NULL;
head = ptr;
}
else
{
node* temp = head;
while (temp->next)
{
temp = temp->next;
}
temp->next = ptr;
ptr->prev = temp;
ptr->next = NULL;
ptr->val = value;
}
return head;
}
Вы можете просто удалить этот аргумент или просто начать использовать возвращаемое значение для обновления заголовка списка.
node* AddNodeAt(node* head, int position, int value)В этом тоже есть ошибки.
Например, если это условие истинно:
node* ptr = (node*)malloc(sizeof(node));
if (head == NULL && position != 1)
{
printf(
"Empty Linklist,cant insert node at the "
"given position");
}
функция напечатает сообщение и вернет head без изменений. Но выделенная память в ptr пропала навсегда...
Также не работает position — это 1, где нужно добавить узел в заголовке.
В любом случае, поскольку значение, возвращаемое функцией, просто игнорируется в main, у списка все равно нет будущего.
main должна быть первой функцией в файле кода. Или если можно в отдельном файле. Таким образом, вы сможете написать множество небольших тестовых программ и протестировать все быстрее.scanf возвращается и int не просто так. прочитайте руководство. Сравнивает возвращаемое значение с количеством ожидаемых элементов. scanf это --- отсюда и название --- сканер, и нормально ничего не читает. Что касается вашей программы... Просто введите e вместо 4 чуть выше и бац: вот и ваша программа.head в вашем случае. Это катастрофа. Используйте аргументы.связанные списки являются контейнерами. Все списки равны: просто --- возможно, пустая --- последовательность узлов. Не данные, просто узлы. Каждый узел содержит (ваш случай) или указывает на одну единицу данных, назовем ее записью. Таким образом, операции в списке не зависят от того, что указано в данный момент. Или не должен. Таким образом, ваш код можно будет повторно использовать для следующих классических упражнений, таких как список тиков фильмов, список воспроизведения музыки, список книг библиотеки, список управления парковкой :D и все другие обычные подозреваемые.
list в предоставленном кодеtypedef struct node node;
struct node
{
node* prev;
int val;
node* next;
};
node* head;
Это просто узел и глобальный указатель на узел. В списке нет даже упоминания.
list альтернатива// this is a node
typedef struct st_node
{
Info* info;
struct st_node* prev; // links
struct st_node* next;
} Node;
// this is a list
typedef struct
{
size_t size;
Node* head;
Node* tail;
} List;
Теперь у нас есть связанный список. И в списке есть метаданные: ожидаемый минимум: указатели на заголовок и хвост и счетчик размера. И вы видите, что жизнь может быть проще: у каждого List есть своя head, tail и size вещь.
А что с узлом? Каждый узел имеет ссылки и указатель на какую-то вещь. Таким образом, вы можете иметь списки чего угодно: сами данные даже не упоминаются в узле, кроме имени.
Вы можете объявить
List one;
List other = { 0, NULL, NULL };
List* set[30];
и иметь списки Info и one и массив из 30 указателей на списки от other до set[0].
set[29] операции
List* so_create_list(void);
List* so_delete_list(List*);
int so_insert(Info*, List*, int (*compare)(void*, void*));
int so_insert_at(int position, Info* value, List* list);
int so_insert_back(Info*, List*);
int so_insert_front(Info*, List*);
int so_print_list(FILE*,List*,const char*);
int so_sort_nodes(List*, int (*compare)(void*, void*));
Написав таким образом, мы видим, что узлы являются внутренними по отношению к списку и не присутствуют ни в одном списке аргументов. Мы используем только указатели на List и List, поэтому, если список изменится или даже если Info изменится полностью, от Info в этом примере до сложной динамически выделяемой многоуровневой структуры, это не будет иметь никакого значения для самого списка.
Фактически, если каждый узел содержит указатель на запись данных, все, что нужно знать списку, — это то, как
int это называется конструктором копирования.C++ это называется деструктором.C++.toStringC.Если мы предоставим это в список, это может быть список чего угодно. Универсальный и полезный. Я не буду сейчас это реализовывать, но надеюсь, что вы поймете идею из кода: это всего лишь вопрос написания этих узловых операций как функций и использования их в нужных местах.
qsortЭта функция встречается в основном в студенческих заданиях. Не имеет особого смысла обращаться к данным в связанных списках по позиции. Если это важно, мы, вероятно, будем использовать массивы или хеш-таблицы. Связанные списки созданы для навигации по ссылкам.
В любом случае, возможная реализация приведена в примере кода, как и в некоторых случаях использования.
Ниже приведен пример использования insert_at(int position, int value, List* list); внутри узла в качестве данных.
int: список функций для примера#include <stdio.h>
#include <stdlib.h>
// these are operations on data
int so_cmp_info(void* a, void* b);
int so_print_info(int, const char*);
// this is a node
typedef struct st_node
{
int info;
struct st_node* prev; // links
struct st_node* next;
} Node;
// this is a list
typedef struct
{
size_t size;
Node* head;
Node* tail;
} List;
// operations on List
List* so_create_list(void);
List* so_delete_list(List*);
int so_insert(int, List*, int (*compare)(void*, void*));
int so_insert_at(int position, int value, List* list);
int so_insert_back(int, List*);
int so_insert_front(int, List*);
int so_print_list(List*, const char*);
int so_print_list_r(List*, const char*);
int so_sort_nodes(List*, int (*compare)(void*, void*));
Поскольку list.h не является распространенной операцией для связанных списков, so_insert_at() также не является распространенной операцией. Это здесь просто для того, чтобы показать, что все, что нам нужно для сортировки, это:
Наличие функции сравнения 2-х записей облегчает написание
int so_insert(int, List*,int (*compare)(void*, void*));
для вставки записей в определенном порядке, например ISBN для списка книг или продолжительность песни для списков воспроизведения. У нас может быть много функций сравнения с разными критериями. Если мы изменим критерии, необходимо отсортировать список с использованием новых критериев перед вставкой с использованием новой функции сравнения, и это причина использования функции сортировки.
Возможная реализация so_sort_nodes() приведена в примере.
Несколько примеров:
List* so_create_list(void)
{
List* list = malloc(sizeof(List));
if (list == NULL) return NULL;
list->head = NULL;
list->tail = NULL;
list->size = 0;
fprintf(stderr, "list created\n");
return list;
}
Это возможный способ создания списка. Использовать его так же просто, как в примере:
List* list = so_create_list();
so_insert возвращается в случае ошибки.
// inserts 'info' at the tail of the list
int so_insert_back(int info, List* list)
{
if (list == NULL) return -1; // no list
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL) return -2; // no alloc
// copy the record pointed by 'info'
node->info = info;
if (list->size == 0) // first node
{
node->next = NULL;
node->prev = NULL;
list->size = 1;
list->head = node;
list->tail = node;
return 0; // 1st node
};
node->next = NULL;
node->prev = list->tail;
list->tail->next = node;
list->tail = node;
list->size += 1;
return 0;
}
Это простая реализация NULL, которая вставляет запись в конец списка. insert_back() аналогичен, поскольку в списке имеются указатели на голову и хвост.
List* list = so_create_list();
if (list == NULL) return -1;
for (int info = 1; info <= 10; info += 2)
so_insert_back(info, list);
so_print_list(list, "\tinserted 1 to 9 ==>\n\n");
for (int info = -1; info >= -10; info -= 2)
so_insert_front(info, list);
so_print_list(list, "\tinserted -1 to -9 ==>\n\n");
В этих строках из примера некоторые записи вставляются в начало и конец списка и распечатываются. Выход:
list created
inserted 1 to 9 ==>
5 data points:
First: 1 Last: 9
1 3 5 7 9
inserted -1 to -9 ==>
10 data points:
First: -9 Last: 9
-9 -7 -5 -3 -1 1 3 5 7 9
И мы видим удобство неинтерактивного кода и возможность принятия дополнительного заголовка в insert_front()
В качестве примера упорядочения эти строки в примере
so_sort_nodes(list, so_cmp_info);
so_print_list(list, "\tsorted descending value ==>\n\n");
это все, что нам нужно, чтобы отсортировать список на месте в порядке убывания --- в любом случае на основе функции сравнения.
so_print_list() пример реализации этих функций#include "List.h"
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
Node* so_locate_at(List* list, size_t pos);
int so_swap_info(Node* one, Node* other);
// list related functions
List* so_create_list(void)
{
List* list = malloc(sizeof(List));
if (list == NULL) return NULL;
list->head = NULL;
list->tail = NULL;
list->size = 0;
fprintf(stderr, "list created\n");
return list;
}
List* so_delete_list(List* del)
{
if (del == NULL) return NULL; // no list
Node* save = NULL;
for (size_t i = 0; i < del->size; i += 1)
{ // delete nodes, 1 by 1
save = del->head->next;
// delete the record pointed by 'head'
free(del->head);
del->head = save;
};
free(del); // delete list
fprintf(stderr, "list deleted\n");
return NULL;
}
int so_insert(
int value, List* list, int (*cmp)(void*, void*))
{
if (list == NULL) return -1; // no list
Node* p = list->head;
for (size_t i = 0; i < list->size; i += 1)
{ // cmp() > 0 marks the insertion point
if (cmp(&value, &p->info) > 0)
{
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL) return -4; // no alloc
node->info = value;
// link the new node before 'p'
if (p == list->head)
return so_insert_front(value, list);
p->prev->next = node;
node->next = p;
node->prev = p->prev;
p->prev = node;
// update size
list->size += 1;
return 0;
}
p = p->next;
}
// all nodes ordered. insert at the end
return so_insert_back(value, list);
}
// inserts 'val' at 'position' in 'List'
// first position is 1
int so_insert_at(int position, int val, List* list)
{
if (list == NULL) return -1;
// insert at head?
if (position == 1) return so_insert_front(val, list);
if (list->size == 0) return -2; // empty list
if (position > list->size) return -3;
if (position == list->size)
return so_insert_back(val, list);
// ok: just advance pointer 'position'-1 times
Node* p = list->head;
for (int i = 1; i < position; i += 1) p = p->next;
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL) return -4; // no alloc
node->info = val;
// link the new node before 'p'
p->prev->next = node;
node->next = p;
node->prev = p->prev;
p->prev = node;
// update size
list->size += 1;
return 0;
}
// inserts 'info' at the tail of the list
int so_insert_back(int info, List* list)
{
if (list == NULL) return -1; // no list
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL) return -2; // no alloc
// copy the record pointed by 'info'
node->info = info;
if (list->size == 0) // first node
{
node->next = NULL;
node->prev = NULL;
list->size = 1;
list->head = node;
list->tail = node;
return 0; // 1st node
};
node->next = NULL;
node->prev = list->tail;
list->tail->next = node;
list->tail = node;
list->size += 1;
return 0;
}
// inserts 'info' at the head of the list
int so_insert_front(int info, List* list)
{
if (list == NULL) return -1; // no list
Node* node = (Node*)malloc(sizeof(Node));
if (node == NULL) return -2; // no alloc
// copy the record pointed by 'info'
node->info = info;
if (list->size == 0)
{
node->next = NULL;
node->prev = NULL;
list->size = 1;
list->head = node;
list->tail = node;
return 0; // 1st node
};
node->next = list->head;
node->prev = NULL;
list->head->prev = node;
list->head = node;
list->size += 1;
return 0;
}
int so_print_list(List* list, const char* msg)
{
FILE* out = stdout;
if (list == NULL)
{
fprintf(out, "No valid list!\n");
return 0;
}
if (list->size == 0)
{
fprintf(out, "list is empty\n");
return 0;
}
if (msg != NULL)
printf(
"\n%s%zd data points:\nFirst: %d Last: %d\n",
msg, list->size, list->head->info,
list->tail->info);
else
printf(
"\n%zd data points:\nFirst: %d Last: %d\n",
list->size, list->head->info, list->tail->info);
Node* p = list->head;
for (size_t i = 0; i < list->size; i += 1)
{
so_print_info(p->info, NULL);
p = p->next;
}
printf("\n\n");
return 0;
}
int so_print_list_r(List* list, const char* msg)
{
FILE* out = stdout;
if (list == NULL)
{
fprintf(out, "No valid list!\n");
return 0;
}
if (list->size == 0)
{
fprintf(out, "list is empty\n");
return 0;
}
if (msg != NULL)
printf(
"\n%s%zd data points (reverse order):\nFirst: "
"%d Last: %d\n",
msg, list->size, list->head->info,
list->tail->info);
else
printf(
"\n%zd data points (reverse order):\nFirst: %d "
" Last: %d\n",
list->size, list->head->info, list->tail->info);
Node* p = list->tail;
for (size_t i = 0; i < list->size; i += 1)
{
so_print_info(p->info, NULL);
p = p->prev;
}
printf("\n[-----]\n\n");
return 0;
}
// return a pointer to a copy of the record
// at such 'pos', or 'NULL'. 'pos'starts at 0
Node* so_locate_at(List* list, size_t pos)
{
if (list == NULL) return NULL;
if (list->size < 1 + pos) return NULL;
Node* nd = list->head;
for (size_t i = 0; i < pos; i += 1) nd = nd->next;
return nd;
}
int so_sort_nodes(List* list, int (*cmp)(void*, void*))
{
if (list == NULL) return -1;
if (list->size < 2) return -2;
if (cmp == NULL) return -3;
for (int i = 0; i < list->size - 1; i += 1)
for (int j = 0; j < list->size - i - 1; j += 1)
{
Node* one = so_locate_at(list, j);
if (cmp((void*)one, (void*)one->next) < 0)
so_swap_info(one, one->next);
}
return 0;
}
// swap data from these 2 nodes
int so_swap_info(Node* one, Node* other)
{
if (one == NULL) return -1;
if (other == NULL) return -1;
int temp = one->info;
one->info = other->info;
other->info = temp;
return 0;
}
int so_cmp_info(void* a, void* b)
{
if (a == NULL) return 0;
if (b == NULL) return 0;
int ta = ((Node*)a)->info;
int tb = ((Node*)b)->info;
if (ta > tb) return +1;
if (ta < tb) return -1;
return 0;
};
int so_print_info(int info, const char* msg)
{
if (msg != NULL) printf("%s", msg);
printf("%4d ", info);
return 0;
}
list.c для примераЭтот код создает список и тестирует некоторые функции. Список распечатывается на каждом этапе. В конце список сортируется, отображается и удаляется.
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
int main(void)
{
List* list = so_create_list();
if (list == NULL) return -1;
for (int info = 1; info <= 10; info += 2)
so_insert_back(info, list);
so_print_list(list, "\tinserted 1 to 9 ==>\n\n");
for (int info = -1; info >= -10; info -= 2)
so_insert_front(info, list);
so_print_list(list, "\tinserted -1 to -9 ==>\n\n");
// insert at the tail using so_insert_at()
so_insert_at((int)list->size, 10, list);
so_insert_at((int)list->size, 11, list);
so_print_list(
list, "\tinserted 10 & 11 at the end ==>\n\n");
// inser at head using so_insert_at()
so_insert_at(1, -10, list);
so_insert_at(1, -11, list);
so_print_list(
list, "\tinserted -10 & -11 at the head ==>\n\n");
so_insert_at(9,2, list);
so_print_list(list, "\tinserted 2 at pos 9 ==>\n\n");
so_insert_at(11,4, list);
so_print_list(list, "\tinserted 4 at pos 11 ==>\n\n");
so_insert_at(13,6, list);
so_print_list(list, "\tinserted 6 at pos 13 ==>\n\n");
so_sort_nodes(list, so_cmp_info);
so_print_list(list, "\tsorted descending value ==>\n\n");
so_delete_list(list);
return 0;
}
list created
inserted 1 to 9 ==>
5 data points:
First: 1 Last: 9
1 3 5 7 9
inserted -1 to -9 ==>
10 data points:
First: -9 Last: 9
-9 -7 -5 -3 -1 1 3 5 7 9
inserted 10 & 11 at the end ==>
12 data points:
First: -9 Last: 11
-9 -7 -5 -3 -1 1 3 5 7 9 10 11
inserted -10 & -11 at the head ==>
14 data points:
First: -11 Last: 11
-11 -10 -9 -7 -5 -3 -1 1 3 5 7 9 10 11
inserted 2 at pos 9 ==>
15 data points:
First: -11 Last: 11
-11 -10 -9 -7 -5 -3 -1 1 2 3 5 7 9 10 11
inserted 4 at pos 11 ==>
16 data points:
First: -11 Last: 11
-11 -10 -9 -7 -5 -3 -1 1 2 3 4 5 7 9 10 11
inserted 6 at pos 13 ==>
17 data points:
First: -11 Last: 11
-11 -10 -9 -7 -5 -3 -1 1 2 3 4 5 6 7 9 10 11
sorted descending value ==>
17 data points:
First: 11 Last: -11
11 10 9 7 6 5 4 3 2 1 -1 -3 -5 -7 -9 -10 -11
list deleted
Этот небольшой пример показывает, как вставлять данные, упорядоченные по некоторым критериям:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
int main(void)
{
srand(240605);
List* list = so_create_list();
if (list == NULL) return -1;
for (int i = 0; i < 20; i += 1)
so_insert(rand()%100, list, so_cmp_info);
so_print_list(list, "\tinserted 20 elements with values from [0..99] ==>\n");
// force insert at the end
so_insert(1000, list, so_cmp_info);
so_print_list(list, "\tinserted 1000 ==>\n");
// force insert at the head
so_insert(-1000, list, so_cmp_info);
so_print_list(list, "\tinserted -1000 ==>\n");
so_delete_list(list);
return 0;
}
list created
inserted 20 elements with values from [0..99] ==>
20 data points:
First: 99 Last: 3
99 94 91 89 86 85 84 83 79 79 72 62 61 42 37 36 35 22 12 3
inserted 1000 ==>
21 data points:
First: 1000 Last: 3
1000 99 94 91 89 86 85 84 83 79 79 72 62 61 42 37 36 35 22 12 3
inserted -1000 ==>
22 data points:
First: 1000 Last: -1000
1000 99 94 91 89 86 85 84 83 79 79 72 62 61 42 37 36 35 22 12 3 -1000
list deleted
Это немного не по теме, здесь только для полноты картины.
Использование возврата к обновлению головы сработало и устранило проблему. Спасибо. Я также переместил main наверх и объявил функции вверху. Это было очень полезно и помогло мне решить аналогичную проблему в коде двоичного дерева.
Эти объявления struct node { node *prev; интервал значений; узел *следующий; };typedef struct node node; не правы. В объявлении структуры имя узла не определено. Код можно скомпилировать, только если вы используете компилятор C++ вместо компилятора C.