问题
I've tried searching for a problem similar to mine, but haven't found much help.
I have a linked list of structs of this type:
struct PCB {
struct PCB *next;
int reg1, reg2;
};
I first create 10 PCB structs linked together in this way:
for(i=20;i<=30;i++) {
curr = (struct PCB *)malloc(sizeof(struct PCB));
curr->reg1 = i;
curr->next = head;
head = curr;
}
I then need to create 20 more PCB structs, but their reg1
values need to be generated using rand()
. I'm currently doing that as so:
for (j = 0;j<20;j++) {
curr = (struct PCB *)malloc(sizeof(struct PCB));
curr->reg1 = rand()%100;
curr->next = head;
head = curr;
}
However, when inserting these PCB structs into the linked list with random reg1
values, I need to be inserting them in the linked list in order (insertion sort). What is the best way to approach this in just a single-link linked list? Thanks
EDIT: I am now keeping track of the first created struct to be able to loop through the linked list from the beginning:
// 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;
}
Then, when I'm creating the additional 10 PCB structs that need to be insertion sorted:
// 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;
}
But this immediately crashed my program.
回答1:
Here is the simplified version of @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;
}
The idea is simple: there need not be any special cases, in any case: a pointer needs to be changed, this could be the root pointer, or the tail pointer, or some pointer in the midddle of the LL. In any/every case:
- the new node actually steals this pointer:
- it makes it point at itself
- it adopts the previous value as a successor (assigns it to its
->next
pointer.
回答2:
The "best" way would probably be to implement a new function for the insertion. This function would iterate over the list until it finds a node whose next
nodes value is less or equal to the node you want to insert, then put the new node before the next
node.
How about this function:
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;
}
}
You would call it like this:
insert(&root, rand() % 100, 0);
来源:https://stackoverflow.com/questions/15960040/insertion-sort-on-linked-list-in-c