对双向链表C ++进行排序

时间:2009-09-05 02:22:24

标签: c++ sorting linked-list

尝试通过遍历列表的循环来完成。

在循环中,我将头节点送入我已定义的排序函数,然后我使用strcmp来确定节点中的哪个名称应该首先出现。

因为过早写名字而无法正常工作。

我通过一次向下列出一个节点并且不回去查看第一个节点是否应该在最后一个节点之前线性地比较它们。解释的部分会有所帮助。

现在对我来说最重要的两个函数定义如下: 我尽力做我认为适合排序功能的事情。

void list::displayByName(ostream& out) const
{
    list *ListPtr = NULL;
    node *current_node = headByName;
    winery *wine_t = new winery(); 
    // winery is another class object type
    // im allocating it to prevent a crash when I call it.

    while ( current_node != NULL )
    {
        *(wine_t) = current_node->item;
        wine_t = ListPtr->sort( current_node );
        out << wine_t << endl;
        current_node = current_node->nextByName;
    }
    delete wine_t;
}

winery * const list::sort( node * current_node ) const
{
    // current_node is the first node.
    const char *SecondName = NULL, *FirstName  = NULL;
    winery *wine_t   = new winery();

    if ( current_node != NULL )
    {
        SecondName   = current_node->item.getName();            
        current_node = current_node->nextByName;
        FirstName    = current_node->item.getName();
    }

    if ( strcmp( FirstName, SecondName ) == -1 )
    {
        *(wine_t)  = current_node->item;
        FirstName  = NULL;
        SecondName = NULL;
        return wine_t;
    }
    else if ( strcmp( FirstName, SecondName ) == 1 )
    {
        *(wine_t) = current_node->item;
        FirstName = NULL;
        SecondName = NULL;
        return wine_t;
    }
    else return wine_t;// then the strings are equal

    FirstName  = NULL;
    SecondName = NULL;
    return wine_t;
}

我开始在这里开发我的节点:

void list::insert(const winery& winery)
{
    node *current_node = new node( winery );

    if ( headByName == NULL )
    {
        headByName   = current_node;
        headByRating = current_node;
        tail         = headByName;
        current_node->prev = current_node;
    }
    else
    {
        current_node->prev = tail;
        tail->nextByName   = current_node;
    }

    tail = current_node;
    current_node = NULL;
}

我认为它在上面的那个函数中是正确的。我可以在那里排序吗?

以下是我正在使用的可变项:

public list
{
         ...
    void insert(const winery& winery);
    void displayByName(ostream& out) const;
}
private:
    struct node
    {
        node(const winery& winery);     // constructor
        winery item;
        node * prev;
        node * nextByName;
        node * nextByRating;
    };

    winery * const sort(node*) const;
    node * headByName;
    node * headByRating;
    node * tail;
};

感谢任何帮助。 非常感谢=)

5 个答案:

答案 0 :(得分:4)

在我提出问题之前,我发现了一些您可能想要解决的问题:

  • 您的节点有两种不同的next,但只有一种prev。这真的是你想要的,如果是,那nextprev配对了吗?
  • 您命名为sort 的方法不会排序,而是作为比较。
  • 您似乎没有实现实际排序(或者至少您没有在此处展示过它)。
  • FirstName中不需要将SecondNameNULL重复设置回sort。它们是局部变量,当方法返回时简单消失。
  • strcmp中无需执行两个sort。缓存第一个的结果(int cmp = strcmp(...); ) or use a switch on the value returned by strcmp`。

要对双链接数组进行排序,我会建议其中一个:

  1. 如果允许的话,使用支持std::sort的标准容器(但我猜这是功课,所以可能不是)。我相信std::list符合条件。
  2. 如果排序顺序永不改变,则在插入时排序
  3. 实现一个分区排序(即quicksort),它在这种结构上非常好用(但是通常的示例代码是在数组上给出的,所以你必须要了解正在做什么和为什么之前在链接列表上实现它的正确方法变得明显。)

答案 1 :(得分:3)

为什么不使用std :: list(STL的双向链表)及其相关的排序函数呢?如果你定义了一个运算符&lt;对于你的列表项,它将只是工作,你不必编写一大堆代码只是为了有一个列表并对其进行排序。

答案 2 :(得分:2)

我不打算编写自己的排序功能。我只使用 qsort 。由于它的接口是c而不是c ++,因此使用它只需构建一个对象指针数组,然后使用自己的比较器函数调用qsort。然后从新排序的对象指针数组重建链表。

答案 3 :(得分:2)

根据我的理解,您希望list::sort在列表中找到大于输入的最小节点。

为此,您需要遍历所有元素并保持找到当前最小但更大的节点。

这样的事情:

node * const list::sort( node * given_node ) const
{
    if ( given_node == NULL )
    {
        return NULL;
    }

    // Smallest node found which is greater than given_node.
    node * least_found_node = NULL;

    // Node we are looking at right now.
    node * current_node = given_node->nextByName;

    // Go through all nodes.
    while ( current_node && current_node != given_node )
    {
        // Is this node bigger than the given node?
        if ( strcmp( current_node->item.getName(), given_node->item.getName() ) < 0 )
        {
            // Is this node smaller than the smallest node we know of?
            if ( least_found_node == NULL ||
               ((strcmp( current_node->item.getName(), least_found_node->item.getName() ) > 0) )
            {
                // We found a better node.
                least_found_node = current_node;
            }
        }

        current_node = current_node->nextByName;
    }

    return least_found_node;
}

现在更改您的显示功能以使用它:

void list::displayByName(ostream& out) const
{
    // Find first node initially.
    node * current_node = sort( NULL );

    while ( current_node != NULL )
    {
        // Print node.
        out << current_node->item.getName();

        // Find next node in sorted output.
        current_node = sort( current_node );
    }
}

此部分一直致电sort,直到sort返回NULL。对sort的第一次调用是NULL,因此找到了最低的项目(即排序列表中的第一项)。如果没有更多节点大于sortNULL将返回current_node,从而终止循环。

答案 4 :(得分:0)

如果您正在为链接列表寻找有效的就地排序算法,请查看this one ...我发现它非常快。