Сортировка вставками на связанный список в C?
Я пытался найти проблему, похожую на мою, но не нашел большой помощи.
У меня есть связанный список структур этого типа:
struct PCB {
    struct PCB *next;
    int reg1, reg2;
};
Сначала я создаю 10 печатных плат, связанных между собой следующим образом:
for(i=20;i<=30;i++) {
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = i;
        curr->next  = head;
        head = curr;
    }
reg1 должны быть сгенерированы с помощью rand(). В настоящее время я делаю это так: 
for (j = 0;j<20;j++) {
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = rand()%100;
        curr->next  = head;
        head = curr;
    }
Однако при вставке этих структур печатных плат в связанный список со случайными значениями reg1, я должен быть вставка их в связанный список по порядку (сортировка вставки). Как лучше всего подойти к этому в одном-единственном списке ссылок? Спасибо 
Править: Теперь я отслеживаю первую созданную структуру, чтобы иметь возможность перебирать связанный список с самого начала:
// create root struct to keep track of beginning of linked list
root = (struct PCB *)malloc(sizeof(struct PCB));
root->next = 0;  
root->reg1 = 20;
head = NULL;
// create first 10 structs with reg1 ranging from 20 to 30
for(i=21;i<=30;i++) {
    curr = (struct PCB *)malloc(sizeof(struct PCB));
    // link root to current struct if not yet linked
    if(root->next == 0){
        root->next = curr;
    }
    curr->reg1 = i;
    curr->next  = head;
    head = curr;
}
Затем, когда я создаю дополнительные 10 структур печатных плат, которые должны быть отсортированы по вставке:
// create 20 more structs with random number as reg1 value
    for (j = 0;j<20;j++) {
        curr = (struct PCB *)malloc(sizeof(struct PCB));
        curr->reg1 = rand()%100;
        // get root for looping through whole linked list
        curr_two = root;
        while(curr_two) {
            original_next = curr_two->next;
            // check values against curr->reg1 to know where to insert
            if(curr_two->next->reg1 >= curr->reg1) {
                // make curr's 'next' value curr_two's original 'next' value
                curr->next = curr_two->next;
                // change current item's 'next' value to curr
                curr_two->next = curr;
            }
            else if(!curr_two->next) {
                curr->next = NULL;
                curr_two->next = curr;
            }
            // move to next struct in linked list
            curr_two = original_next;
        }
        head = curr;
    }
2 ответа:
Вот упрощенная версия @Joachim:
void insert(struct PCB **head, const int reg1, const int reg2) { struct PCB *new ; /* Find the insertion point */ for ( ;*head; head = & (*head)->next) { if ((*head)->reg1 > reg1) break; } new = malloc(sizeof *new ); new->reg1 = reg1; new->reg2 = reg2; new->next = *head; *head = new; }Идея проста: не должно быть никаких особых случаев , в любом случае: указатель должен быть изменен, это может быть корневой указатель, или хвостовой указатель, или какой-то указатель в середине LL. В любом / каждом случае:
- новый узел фактически крадет этот указатель:
- она указывает на саму себя
- он принимает Предыдущее значение в качестве преемника (присваивает его к его указателю
->next.
" лучшим " способом, вероятно, было бы реализовать новую функцию для вставки. Эта функция будет перебирать список до тех пор, пока не найдет узел, значение
nextузлов которого меньше или равно узлу, который вы хотите вставить, а затем поместить новый узел перед узломnext.
Как насчет этой функции:
void insert(struct PCB **head, const int reg1, const int reg2) { struct PCB *node = malloc(sizeof(struct PCB)); node->reg1 = reg1; node->reg2 = reg2; node->next = NULL; if (*head == NULL) { /* Special case, list is empty */ *head = node; } else if (reg1 < (*head)->reg1) { /* Special case, new node is less than the current head */ node->next = *head; *head = node; } else { struct PCB *current = *head; /* Find the insertion point */ while (current->next != NULL && reg1 < current->next->reg1) current = current->next; /* Insert after `current` */ node->next = current->next; current->next = node; } }Вы бы назвали это так:
insert(&root, rand() % 100, 0);