【问题标题】:Link List C++ in certain order链表 C++ 按特定顺序
【发布时间】:2020-03-31 19:04:38
【问题描述】:

我必须按照低 -> 高 -> 低 -> 高 -> 低的模式订购给定的链接列表 1 -> 2 -> 3 -> 4 -> 5 导致 1 -> 3 -> 2 - > 5 -> 4.

我已经编码了这个:

#include <iostream>

using namespace std;

struct node
{
    int data;
    node *next;
};

class linked_list
{
private:
    node *head,*tail;
public:
    linked_list()
    {
        head = NULL;
        tail = NULL;
    }

    void add_node(int n)
    {
        node *tmp = new node;
        tmp->data = n;
        tmp->next = NULL;

        if(head == NULL)
        {
            head = tmp;
            tail = tmp;
        }
        else
        {
            tail->next = tmp;
            tail = tail->next;
        }
    }

    node* getHead()
    {
        return head;
    }
};

int main()
{
    linked_list a;
    a.add_node(1);
    a.add_node(2);
    a.add_node(3);
    a.add_node(4);
    a.add_node(5);
    bool leave= false;
    int direction = 1;
    node* considered_node = new node(*(a.getHead()));
    while(true)
    {
        if (considered_node->next == NULL)
        {
            break;
        }
        else if (direction*considered_node->next->data < direction*considered_node->data)
        {
            int t= direction*considered_node->next->data;
            int p = direction*considered_node->data;
            int tmp = considered_node->next->data;
            considered_node->next->data = considered_node->data;
            considered_node->data = tmp;
        }
        delete considered_node;
        considered_node = considered_node->next;
        direction = -1*direction;
    }
    return 0;
}

但是我在迭代链接列表并删除指针以避免内存泄漏的方式上犯了一个错误。我不想只更改 for 循环的链接列表的声明。

【问题讨论】:

  • delete considered_node; considered_node = considered_node-&gt;next; 是未定义行为,因为您在删除后访问内存。
  • 不是必需的,但无论如何应该只是一对一的比较,所以你应该最多将每个元素移动 1 个位置。所以我希望它可以生成任何订单
  • 在 for 循环之后移动你的 delete considered_node;
  • 在完成for循环后删除considered_node之前还要添加considered_node-&gt;next-&gt;data = considered_node-&gt;data;
  • 顺便说一句,这是一个“链接”列表

标签: c++ class linked-list swap singly-linked-list


【解决方案1】:

如果我对分配的理解正确,那么当第一个节点不得大于第二个节点且第二个节点不得小于第三个节点时,您需要重新排序列表,依此类推。

如果是这样,则无需使用运算符 new 重新排序列表。

这是一个演示程序。我对列表定义做了一些小的改动。例如,结构节点应该对列表的用户隐藏。它应该被定义为列表定义中的私有数据成员。

#include <iostream>
#include <utility>

class linked_list
{
private:
    struct node
    {
        int data;
        node *next;
    } *head = nullptr, *tail = nullptr;

public:
    linked_list() = default;

    void add_node( int data )
    {
        node *tmp = new node { data, nullptr };

        if ( head == NULL )
        {
            head = tail = tmp;
        }
        else
        {
            tail = tail->next = tmp;
        }
    }

    void reorder()
    {
        int direction = 0;

        auto condition = [&direction]( const auto &a, const auto &b )
        {
            return ( direction ^= 1 ) ?  b < a : a < b;
        };

        node **current = &head;

        for ( ; *current && ( *current )->next; current = &( *current )->next )
        {
            if ( condition( ( *current )->data, ( *current )->next->data ) )
            {   
                node * &next = ( *current )->next;
                std::swap( *current, next );
                std::swap( ( *current )->next, next->next );
            }
        }

        tail = *current;
    }

    friend  std::ostream & operator <<(std::ostream &os, const  linked_list &list)
    {
        for ( const node *current = list.head; current != nullptr; current = current->next)
        {
            os << current->data << " -> ";
        }

        return os << "null";
    }   
};

int main() 
{
    linked_list list;
    int a[] = { 1, 2, 3, 4, 5 };

    for ( int data : a ) list.add_node( data );

    std::cout << list << '\n';

    list.reorder();

    std::cout << list << '\n';

    int b[] = { 6, 7, 8, 9, 10 };

    for ( int data : b ) list.add_node( data );

    std::cout << list << '\n';

    list.reorder();

    std::cout << list << '\n';

    return 0;
}

它的输出是

1 -> 2 -> 3 -> 4 -> 5 -> null
1 -> 3 -> 2 -> 5 -> 4 -> null
1 -> 3 -> 2 -> 5 -> 4 -> 6 -> 7 -> 8 -> 9 -> 10 -> null
1 -> 3 -> 2 -> 5 -> 4 -> 7 -> 6 -> 9 -> 8 -> 10 -> null

请注意,在重新排序列表后,您必须调整列表的指针尾部。否则向列表中添加新元素可能无效。

【讨论】:

  • @HectorEstebanCabezos 是的,有一个指向指针的指针。这意味着您正在通过指针间接地通过引用(在 C 中)处理指针头。
  • @HectorEstebanCabezos 想象一下,你已经写了例如 node *current = head;在这种情况下,如果您将更改变量 current 的值,例如 current = nullptr;变量头的值不会改变。但是如果你会写 node **current = &head;那么在这个语句中 *current = nullptr;指针头的值将变为nullptr。
  • @HectorEstebanCabezos 类似于以下内容。诠释 x = 10;整数 y = x; y = 20;如您所见,变量 x 的值不会改变。但是如果你会写 int x = 10; int *y = &x; *y = 20;将要更改的是变量 x。
  • @HectorEstebanCabezos 是的,没有足够经验的时候很难理解。
  • @HectorEstebanCabezos 这声明了对指向节点的指针的引用。
【解决方案2】:

在这里,我试图解释一下。见,https://ideone.com/PdBY6W

int direction = 1;

node* considered_node = new node(*(a.getHead()));
while(true)
{
    if (considered_node->next == NULL)
    {
        break;
    }

    // do not need else here
    if (direction*considered_node->next->data < direction*considered_node->data)
    {
        // do not need t and p
        // int t= direction*considered_node->next->data;
        // int p = direction*considered_node->data;
        int tmp = considered_node->next->data;
        considered_node->next->data = considered_node->data;
        considered_node->data = tmp;
    }

    // if you delete considered_node, then you can not access it's address
    // after deleting it. So comment the deletion
    // delete considered_node;
    considered_node = considered_node->next;
    direction = -1*direction;
}

// Notice after finishing the for loop, considered_node is now at the tail
// node of the list. So, before deleting considered_node move it's reference
// to the next node and then delete. Otherwise, if you delete without moving
// the reference, the deletion will delete the tail node, in which case the 
// list will be 1-> 3 -> 2 -> 5 -> 0.
considered_node = considered_node->next;
delete considered_node;

// now the list is 1-> 3 -> 2 -> 5 -> 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-23
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-07
    相关资源
    最近更新 更多