在单个链接列表上使用插入排序

时间:2012-11-18 19:35:53

标签: c++ list sorting linked-list insertion-sort

所以我有一个任务,我给出一个随机的数字列表,我需要使用插入排序对它们进行排序。我必须使用单链表。我环顾四周其他帖子但似乎没有任何帮助。我得到什么插入排序但我只是不知道如何在代码中写它。

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;
}

我不知道这是对的还是现在做什么

7 个答案:

答案 0 :(得分:5)

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;
    }
}

答案 1 :(得分:3)

让我们考虑插入排序是如何工作的:它将(在理论上)“列表”拆分为三组:排序的子集(可能为空),当前项和未排序的子集(可能为空)。当前项目之前的所有内容都已排序。当前项目之后的所有内容可能会也可能不会被排序。该算法检查当前项,将其与下一项进行比较。请记住,当前项目之后的第一个项目属于未排序的子集。

让我们假设您按递增顺序对整数进行排序(因此给出“3,1,5,2,4”您想得到“1,2,3,4,5”)。您将当前项目设置为列表中的第一项。现在开始排序:

如果下一个项目大于当前项目,则无需对该项目进行排序。只需将其设为“当前项目”并继续。

如果下一个项目小于当前项目,那么您还有一些工作要做。首先,将下一个项目保存在某个位置 - 让我们说一个名为temp的指针 - 然后通过使current-&gt; next = current-&gt; next-&gt; next来“删除”列表中的下一个项目。现在,您需要找到已删除项目的正确位置。您可以通过两种方式执行此操作:

  1. 从列表的开头开始,直到找到正确的位置。完成后,将项目插入其中,然后继续插入排序。如果你有一个单链表,这是最简单的解决方案。
  2. 你向后走,直到找到该物品的正确位置。完成后,将项目插入其中,然后继续插入排序。如果您有一个双向链接列表,这可能会更复杂,但可以很好地工作。
  3. 您继续此过程,直至到达列表末尾。到达目的地后,您就知道已完成插入排序,并且列表的排序顺序正确。

    我希望这会有所帮助。

答案 2 :(得分:1)

考虑一下 - 如果列表为空,temp最初为NULL,那么当您执行temp->next = head;时就会出现未定义的行为。

尝试一些调试,肯定会有所帮助。您可能要么也要保留上一个节点,这样您可以在之后插入,或者向前看2个节点。

答案 3 :(得分:1)

哇,我确定聚会晚了吧?无论如何,我想花两分钱回答这个问题。根据您提供示例代码的方式,我将假设以下内容:

  1. 您没有使用OOP原则
  2. 您已经正确设置了单链接列表(我将其称为转发列表
  3. 您希望用户在调用实现函数时使用运算符'='

首先,我要给您的答案将使用我喜欢的双指针技术!在哪里使用双指针来帮助您同时引用两个变量,以便在达到 nullptr 时避免复杂的测试案例。

好吧,好吧...我在叫法中输掉了 pointer-to-pointer double pointer ,我可能会因为把它称为a 技术!如果您精通了指针的概念,那么我要向您展示的内容应该是微不足道的。我称指针对指针为技术,因为很少有人谈论它或在示例源代码中使用它!以下link将带您进入由Semmy Purewal创建的博客,其中将详细讨论该概念!

forward_list *insertion_sort( forward_list *head )
{
  /// Ensure provided linked list is not empty and has more than one element...
  if( head == nullptr || head -> next == nullptr )
  {
    std::cout << "Error: empty or single element linked list provided!\n";
    return;
  }

  /// Initialize separate variable the houses a growing sorted output...
  forward_list *sorted = nullptr;

  /// Traverse provided singly linked list...
  while( head != nullptr )
  {
    /// Remember current head before popping it off...
    forward_list *current_head = head;

    /// Double pointer for effective splicing of unsorted singly linked list...
    forward_list **trail = &sorted;

    /// Now we pop off the current head...
    head = head -> next;

    /// Iterate through our growing sorted output to figure out where we need to the head...
    while( ( *trail ) != nullptr && ( *trail ) -> data > current_head -> data )
    {
      /// Head does not belong in this current position, move on!
      trail = &( *trail ) -> next;
    }

    /// Insert the head and update our growing sorted output to point to the head...
    current_head -> next = ( *trail );
    ( *trail ) = current_head;
  }

  /// Return our sorted output...
  return sorted;
}

现在,您有了插入排序的示例实现,该示例可在单链列表上出色地运行!此实现没有 nullptr 的混乱测试用例,因为我们使用了一个名为 trail 的双指针,它可以跟踪自身以及指向不断增长的排序输出的指针。因此,当算法遍历排序的输出时,变量 trail nullptr 处被取消引用,该变量保留了最后一个节点的 next 指针!

总而言之,我希望您对这个答案既有帮助,又有更多可读性!我知道这个问题是在7年前提出的,而只是在一年之前才开始使用,但是我希望有人觉得这个问题有用。小子,那我走了!

答案 4 :(得分:1)

我已经使用类而不是struct对其进行了编码。可以进行更改,但算法相同。 用于创建节点和单个链接列表的类的代码。

#include<iostream>
using namespace std;

class node{
    public:
    int data;
    node* next;
};

class list{
    node* head;

    public:
    list() {
        head=NULL;
    }

    void add(int el) {
        node* newNode=new node();

        newNode->data=el;
        newNode->next=NULL;

        if(head==NULL) {
            head=newNode;
        } else {
            node* temp=head;

            while(temp->next!=NULL) {
                temp=temp->next;
            }
            temp->next=newNode;
        }
    }

//Insertion sort code

    void insertionSort() {
        node* i=head->next;

        while (i!=NULL)
        {
            node* key=i;
            node* j=head;

            while (j!=i)
            {
                if (key->data<j->data)
                {
                    int temp=key->data;
                    key->data=j->data;
                    j->data=temp;
                }
                j=j->next;
            
            }
            i=i->next;
        }
    }

    void display() {
        node* temp=head;

        while (temp!=NULL) {
            cout<<temp->data<<" ";
            temp=temp->next;
        }
    
    }
};

用于创建主文件:

int main()
{
    list l;
    l.add(2);
    l.add(6);
    l.add(0);
    l.add(3);
    l.add(7);
    l.add(4);

    l.insertionSort();
    l.display();
}

请纠正我,如果它不起作用或者插入条件未正确实施。

答案 5 :(得分:0)

这是链表上插入排序的Java实现:

  
      
  • 时间复杂度:O(n ^ 2)
  •   
  • 空间复杂度:O(1)-插入排序是就地排序算法
  •   
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;
    }
}

答案 6 :(得分:-1)

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;
    }
}