所以我有一个任务,我给出一个随机的数字列表,我需要使用插入排序对它们进行排序。我必须使用单链表。我环顾四周其他帖子但似乎没有任何帮助。我得到什么插入排序但我只是不知道如何在代码中写它。
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;
}
我不知道这是对的还是现在做什么
答案 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来“删除”列表中的下一个项目。现在,您需要找到已删除项目的正确位置。您可以通过两种方式执行此操作:
您继续此过程,直至到达列表末尾。到达目的地后,您就知道已完成插入排序,并且列表的排序顺序正确。
我希望这会有所帮助。
答案 2 :(得分:1)
考虑一下 - 如果列表为空,temp
最初为NULL
,那么当您执行temp->next = head;
时就会出现未定义的行为。
尝试一些调试,肯定会有所帮助。您可能要么也要保留上一个节点,这样您可以在之后插入,或者向前看2个节点。
答案 3 :(得分:1)
哇,我确定聚会晚了吧?无论如何,我想花两分钱回答这个问题。根据您提供示例代码的方式,我将假设以下内容:
首先,我要给您的答案将使用我喜欢的双指针技术!在哪里使用双指针来帮助您同时引用两个变量,以便在达到 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;
}
}