不使用交换的单链表中的选择排序

Posted

技术标签:

【中文标题】不使用交换的单链表中的选择排序【英文标题】:Selection sort in single linked list without using swap 【发布时间】:2021-12-09 15:29:07 【问题描述】:

我一直在尝试在不使用交换节点的情况下解决单链表中的选择排序问题。使用临时列表存储节点并为当前列表分配一个新列表

//my addlastnode function
void AddLastNODE(LIST &mylist, NODE *p)

//Check the list is empty or not
    if(isEmpty(mylist))
        mylist.pHead = mylist.pTail = p;
    else
        mylist.pTail->pNext = p;
        mylist.pTail = p;


void selectionSort(LIST &mylist)

//Initialize a temp list to store nodes 
    LIST mylisttemp;
    IntList(mylisttemp);
//Create node
    NODE *p;
    NODE *i;
//Create min node
    NODE *min;
//Check if list is empty or has one node
    if(mylist.pHead == mylist.pTail)
        return;
//Traverse the list till the last node
    for(p=mylist.pHead; p->pNext!=NULL && p!=NULL; p = p->pNext)
        
            min=p;
                for(i=p->pNext; i!=NULL;i=i->pNext)
                
////Find the smallest data in list
                    if(i->data < min->data)
                        min=i;
                
////Add the smallest to a new list
                AddLastNODE(mylisttemp, min);
        
//Fill the current list to the new list
    if(!isEmpty(mylisttemp))
    mylist = mylisttemp;

【问题讨论】:

您不能只将节点添加到新列表中而不将其从旧列表中彻底删除:在两个列表中拥有相同的节点而只有一个与.next 链接几乎是不可能的。请注意,在迭代列表时删除列表中的节点并不是那么简单。 @JoëlHecht 我明白了,谢谢 【参考方案1】:

您的代码不会减少您从中选择节点的列表:应从中删除所选节点。要做到这一点,您需要对所选节点之前的节点的引用,以便您可以重新连接列表以排除该所选节点。

您的AddLastNODE 函数中还有一个小问题:它不会强制尾节点将空值作为pNext 指针。当使用仍然具有非空 pNext 指针的节点调用函数时,这可能是导致错误的原因。其次,else 块周围的缩进是关闭的。在这种情况下它不会导致错误,但最好避免混淆:

void AddLastNODE(LIST &mylist, NODE *p)

    if(isEmpty(mylist))
        mylist.pHead = p;
    else
        mylist.pTail->pNext = p;
    mylist.pTail = p; // indentation!
    p->pNext = nullptr; // <--- better safe than sorry!

然后到主算法。在查找具有最小值的节点时,使用 previous 节点引用非常繁琐。当您暂时使输入列表循环时,它会有所帮助:

void selectionSort(LIST &mylist) 
    if (mylist.pHead == mylist.pTail) return;
    // Make list temporarily cyclic
    mylist.pTail->pNext = mylist.pHead;

    LIST mytemplist;
    IntList(mytemplist);

    while (mylist.pHead != mylist.pTail) 
        // Select node:
        NODE * beforemin = mylist.pTail;
        for (NODE * prev = mylist.pHead; prev != mylist.pTail; prev = prev->pNext) 
            if (prev->pNext->data < beforemin->pNext->data) 
                beforemin = prev;
            
        
        NODE * min = beforemin->pNext;
        // Extract selected node:
        if (min == mylist.pTail) mylist.pTail = beforemin;
        if (min == mylist.pHead) mylist.pHead = min->pNext;
        beforemin->pNext = min->pNext;
        // And insert it:
        AddLastNODE(mytemplist, min);
    
    // Move last remaining node
    AddLastNODE(mytemplist, mylist.pHead);
    // Copy back
    mylist = mytemplist;

附带说明:您甚至可能希望始终保持列表循环。这意味着您可能会在其他函数中进行一些更改,因为那时不会有为空的pNext 指针。

【讨论】:

以上是关于不使用交换的单链表中的选择排序的主要内容,如果未能解决你的问题,请参考以下文章

算法与数据结构索引

编程-链表之希尔排序堆排序归并排序快速排序

[程序员代码面试指南]链表问题-单链表的选择排序(选择排序)

单链表的折半查找,冒泡排序,选择排序

3.1.1蛮力法之选择排序

算法总结之 单链表的选择排序