Using insertion sort on a singly linked list

2020-05-28 10:55发布

问题:

So I have an assignment where I'm giving a random list of number and I need to sort them using insertion sort. I must use a singly linked list. I looked around at other posts but none seem to help. I get what insertion sort is but I just don't know how to write it in code.

Node* insertion_sort(Node* head) {
  Node* temp = head_ptr;
  while((head->n < temp->n) && (temp != NULL))
    temp = temp->next;
  head->next = temp->next;
  temp->next  = head;
  head->prev = temp;
}

I dont know if this is right or what to do now

回答1:

struct node {
    int data;
    struct node *next;
};


void insertion(struct node **head) {
    if((*head)== NULL || (*head)->next == NULL) {
       return;
    }
    struct node *t1 = (*head)->next;
    while(t1 != NULL) {
        int sec_data = t1->data;
        int found = 0;
        struct node *t2 = *head;
        while(t2 != t1) {
            if(t2->data > t1->data && found == 0) {
                sec_data = t2->data;
                t2->data = t1->data;
                found = 1;
                t2 = t2->next;
            } else {
                if(found == 1) {
                    int temp = sec_data;
                    sec_data = t2->data;
                    t2->data = temp;
                }
                t2 = t2->next;
            }
       }
       t2->data = sec_data;
       t1 = t1->next;
    }
}


回答2:

Let's think about how Insertion Sort works: It "splits" (in theory) the list into three groups: the sorted subset (which may be empty), the current item and the unsorted subset (which may be empty). Everything before the current item is sorted. Everything after the current item may or may not be sorted. The algorithm checks the current item, comparing it with the next item. Remember that the first item after the current item belongs to the unsorted subset.

Let's assume that you are sorting integers in increasing order (so given "3,1,5,2,4" you want to get "1,2,3,4,5"). You set your current item to the first item in the list. Now you begin sorting:

If the next item is greater than the current item, you don't need to sort that item. Just make it "current item" and continue.

If the next item is less than the current item then you have some work to do. First, save the next item somewhere - let's say in a pointer called temp - and then "remove" the next item from the list, by making current->next = current->next->next. Now, you need to find right place for the removed item. You can do this in two ways:

  1. Either start from the beginning of the list, going forward until you find the correct position. Once you do, you insert the item there and you continue your insertion sort. This is the simplest solution if you have a singly-linked list.
  2. You go backwards, until you find the correct spot for the item. Once you do, you insert the item there and you continue your insertion sort. This is a bit more involved but can work well if you have a doubly-linked list.

You continue this process until you reach the end of the list. Once you reach it, you know that you have completed your insertion sort and the list is in the correct sorted order.

I hope this helps.



回答3:

Think about this - if the list is empty, temp will initially be NULL, so you get undefined behavior when you do temp->next = head;.

Try some debugging, it will surely help. You'll probably either want to keep the previous node as well, so you can insert afterwards, or look 2 nodes forward.



回答4:

Here is the Java Implementation of Insertion Sort on Linked List:

  • Time Complexity: O(n^2)
  • Space Complexity: O(1) - Insertion sort is In-Place sorting algorithm
class Solution 
{
    public ListNode insertionSortList(ListNode head)
    {
        // Initialize partially sorted list
        ListNode dummy = new ListNode(0), prev = dummy, current = head;

        while(current != null)
        {
            if(prev.val > current.val)
                prev = dummy;

            // Find the right place to insert current node
            while(prev.next != null && prev.next.val < current.val)
                prev = prev.next;

            // Insert current between prev and prev.next
            ListNode nextNode = current.next;
            current.next = prev.next;
            prev.next = current;
            current = nextNode;
        }
        return dummy.next;
    }
}


回答5:

void linked_list::insertion_sort() {
    node * p = head;
    node * currentNode = head->next; // The node that is being compared at the moment.
    node * previousNode = head; // The node previous to the node being compared at the moment.
    //We can return from the sorting if the length of the linked list is less than 2.
    if (p == nullptr || p->next == nullptr) {
        return;
    }

    while (currentNode != nullptr) {
//If the current node is larger than or equal to the largest element of the sorted linked list on the left, we can move to the next element. 
//Helpful for an already sorted array.
        if(previousNode->value<=currentNode->value){
            currentNode = currentNode->next;
            previousNode = previousNode->next;
        }
        else{
//If the element is the smaller than the head element we need to take care of the head element.
            if (head->value > currentNode->value) {
                previousNode->next = currentNode->next;
                currentNode->next = head;
                head = currentNode;
            }else {
                p = head;
                while (p->next != NULL && p->next->value < currentNode->value) {
                        p = p->next;
                }
                previousNode->next = currentNode->next;
                currentNode->next = p->next;
                p->next = currentNode;
            }
        }
        currentNode = previousNode->next;
    }
}