【问题标题】:Sort Ascending - Linked List [closed]升序排序 - 链表[关闭]
【发布时间】:2014-12-28 20:23:12
【问题描述】:

我在理解这个功能如何工作以及我需要做什么方面遇到了一些麻烦。我有 int number 作为我的数据类型和 node* next 在我的节点类中。我也有节点指针头、电流和温度。我的问题是我将如何让我的整数列表有序?另外,升序和降序如何在单个链表中工作?

我的头文件:

#ifndef SDI_LL                      
#define SDI_LL                      

namespace SDI
{                                                       

    class LinkedList                                                                    
    {
        class Node                                      
        {
        public:
            int number;                                 //data element
            Node* next;                                 //pointer to next, node inside each node
        private:

        };

    private:

        Node *head;
        Node *current;                                  //head, current and temp node pointers
        Node *temp;

    public:
        LinkedList();                                   //constructor to access nodes from above
        ~LinkedList();                                  //destructor

        void insert(int add);                           
        void remove(int remove);                        //functions that access private data nodes above
        void display();
        void reverse();
        void search(int searchNum);
        void sortAscending();
        void sortDecending();
        void saveAll();
        void restoreAll();

    };

}
#endif

到目前为止,我的升序函数从头开始并在列表中搜索:

void LinkedList::sortAscending()
{
    current = head;
    for (current = head; current;)
    {
        temp = current;
        current = current->next;

    }
}

【问题讨论】:

  • 对于内部列表,例如std::list,有一个特殊的列表排序,std::list::sort,但是节点是在类中维护的,类函数复制内部节点和某些用户指定类型(如结构)之间的节点数据,不包括链接。但是在这种情况下,您正在创建自己的节点类和函数(例如您自己的排序),因此标准函数将无济于事。
  • @Ryan - 对于这种列表排序,您是要交换节点中的数据还是交换节点?
  • “搁置” - 原始发帖人计划稍后使用排序功能的实际示例代码更新他的问题。答案之一包括交换数据的示例代码。不知道原贴是打算交换数据还是交换节点。
  • @MSalters:是的。我期待一个专业。删除了错误的评论。

标签: c++ sorting linked-list


【解决方案1】:

一般来说,您应该使用标准库中提供的容器,这些容器在适用的情况下提供了有效的排序方法。

也就是说,如果您想出于学习目的而这样做 - 正如您可能“应该至少一次”那样 - 那么实施起来并不太难。

for (current = head; current;)

这是一个有趣的 for 循环,我个人更喜欢:

current = head;
while(current)  // or current != nullptr to be more explicit

还请注意,您(当然,不必要地)将 head 分配给 current 两次 - 紧接在 for 循环之前,以及在它的初始化中。

一个简单的方案(但根本没有效率!)可能是在您遍历列表时只交换“乱序”元素,直到不需要交换:

bool changeMade;
do{
    changeMade = false;
    current = head;
    while( current ){
        temp = current;
        current = current->next;

        if( current && current->data < temp->data ){
            changeMade = true;
            swap( temp->data, current->data );
        }
    }
} while( changeMade );

这假设 data 字段是节点中唯一的另一个字段 - 因为它实际上并不交换节点,只是交换数据。 (做前者实际上并不困难 - 但如果没有看到您的节点类型声明,我会编造名称并冒着混淆问题的风险。)

【讨论】:

  • std::sort 需要随机访问迭代器,而列表类通常不支持随机访问迭代器。 std::list:sort 可以工作,但列表节点是 std::list 内部的,并且原始帖子正在实现它自己的列表类节点和函数。
  • 与换行有点混淆(temp->data, current->data);
  • 这是什么,交换位是什么?
  • @Ryan 只是一个交换这些位置值的函数。我把它拉出来只是为了简洁,也因为我不知道data的类型,或者是否有多个数据字段。
  • @Ryan - 不确定问题是什么。如果您只是交换数字(数据),则列表指针应该不受影响。您可以更新原始帖子以向您展示最新的代码尝试吗?
【解决方案2】:

我没有看到任何关于 current、head 和 temp 的声明,但我认为它们是指向节点的指针。你决定排序算法了吗?排序算法是否需要高效或具有冒泡排序的性能?使用类似于冒泡排序的逻辑,您可以重复地将具有最大值的节点移动到列表的末尾。或者为了节省一点时间,您可以从原始列表中删除具有最大值的节点并将其插入到新列表的前面,该列表将以排序顺序结束。更高效的算法使用基于归并排序的逻辑。

要删除或交换节点,使用指向指针的指针可以避免对列表的第一个节点(本例中为 pList 指向的节点)进行特殊处理:

NODE * SortList(NODE * pList)
{
NODE * pNew = NULL;                     /* sorted list */
NODE **ppNode;                          /* ptr to ptr to node */
NODE **ppLargest;                       /* ptr to ptr to largest node */
NODE * pLargest;                        /* ptr to largest node */
    while(pList != NULL){               /* while list not empty */
        ppLargest = &pList;             /*  find largest node */
        ppNode = &((*ppLargest)->next);
        while(NULL != *ppNode){
            if((*ppNode)->data > (*ppLargest)->data)
                ppLargest = ppNode;
            ppNode = &((*ppNode)->next);
        }
        pLargest = *ppLargest;          /* move node to new */
        *ppLargest = pLargest->next;
        pLargest->next = pNew;
        pNew = pLargest;
    }    
    return(pNew);
}

【讨论】:

  • @Jasen - 我不小心在答案完成之前发布了我的答案。现在有答案了。
  • @Ryan - 这是您想要做的,还是您会考虑删除节点并将其插入新列表中是更好的选择?如果这是家庭作业,我不确定我们应该为你做多少代码。你能写出找到原始列表中最大节点的代码吗?
  • 是的,这就是我想做的,但我不知道从哪里开始。我只想将其保留为一个列表
  • @Ryan - 要将最大节点移动到末尾,如果当前节点的值大于下一个节点的值,您将扫描列表并将当前节点与下一个节点交换。这里的问题是知道何时完成。使用在扫描开始时清除的标志并设置是否在扫描期间进行任何交换,然后在扫描后检查标志以查看其是否为零是了解何时完成排序的一种方法。跨度>
  • 谢谢 :) 我现在就试试
猜你喜欢
  • 2018-07-26
  • 1970-01-01
  • 1970-01-01
  • 2016-01-09
  • 2012-11-14
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
相关资源
最近更新 更多