【问题标题】:How to traverse deque and search for an element?如何遍历双端队列并搜索元素?
【发布时间】:2020-07-06 06:54:42
【问题描述】:

我有两个这样定义的双端队列

struct elem
{
    int key; elem* next;
}
*left = NULL, *right=NULL, *left2 = NULL, *right2 = NULL;

以及推送和弹出功能

void push_front(int n, elem*&l, elem*&r)
{
    elem *p=left;
    left = new elem;
    left -> key=n;
    left -> next=p;
    if(right==NULL)
    {
        right = left;
    }
}

int pop_front(int &n, elem*&l, elem*&r)
{ 
    elem *p; 
if (left)  
{    
    n=left->key; 
    p=left;    
    left=left->next;
    if (left==NULL)
        right=NULL;    
    delete p;     
    return 1;
}   
else
    return 0;
}

我必须输入搜索功能将使用的整数。出于某种原因,他们要求我首先弹出元素,检查它是否等于输入的数字并重复,直到我们找到元素或者我们是否从第一个双端队列中弹出了所有元素。在要求之前我已经这样做了,但显然它不正确:

void search(int x)
{
    elem *y=left;
    while(y->key!=x)
    {
    if(y==right)
    {
        cout<<x<<" wasn't found, adding to front."<<endl;
        push_front(x);
        return;
    }
    y=y->next;
    }
    cout<<x<<" was found"<<endl;
    return;

}

感谢任何帮助。 而且不,我不能使用 deque 库或 std::find 或类似的东西。

【问题讨论】:

  • std::find - 你为什么不呢?
  • 这是我不使用它的要求...我很久以前使用 std::find 做过这个,但实际上我不允许使用它。
  • 我有两个这样定义的双端队列 -- 你向我们展示的更像是一个单链表,而不是双端队列。

标签: c++ deque


【解决方案1】:

如何遍历双端队列...

这在很大程度上取决于用于实现双端队列的数据结构。 std::deque 例如被实现为数组的链表。遍历列表就像遍历链表一样,除了遍历数组的每个节点。

无论如何,数据结构的遍历通常在 C++ 中通过定义一个迭代器类来实现。给定一个迭代器,遍历可以这样实现:

current = beginning_of_the_range;
last    = end_of_the_range;
for (; current != last; ++current) {
    // current points to current element here
}
struct elem
{
    int key; elem* next;
}

看来您已经使用单链表实现了双端队列。单链表的迭代器可以这样实现:

  • 在迭代器中存储指向当前节点的指针。让我们称之为node
  • 迭代器的间接寻址可以实现为return node-&gt;key;
  • 要移动到下一个元素,请执行node = node-&gt;next;
  • 要检查迭代器是否相等,return node == other.node;
  • 表示结束的迭代器可以表示为 nullptr,或使用哨兵节点。

...然后搜索一个元素?

一旦你实现了遍历,你就可以使用线性搜索了。

【讨论】:

    【解决方案2】:

    对于初学者来说,push_frontpop_front 这两个函数都有拼写错误。在函数中,您必须使用参数标识符lr,而不是标识符leftright

    void push_front(int n, elem*&l, elem*&r)
                           ^^^^^^^^^^^^^^^^
    {
        elem *p=left;
                ^^^^^
        //...
    

    而且您不应该定义全局变量 left、right、left2 和 right2。函数不应依赖于全局变量。

    像搜索这样的功能应该只做一件事:报告元素是否存在于列表中。

    所以函数应该这样定义

    bool search( const elem * &l, int x )
    {
        const elem *current = l;
    
        while ( current != nullptr && current->key != x ) current = current->next;
    
        return current != nullptr;
    }
    

    根据函数的返回值,您可以将值添加到列表中或执行其他操作。

    如果使用辅助列表(效率低下),因为您可能只使用函数 pop_frontpush_front 遍历列表,那么函数可能看起来像

    bool search( elem * &l, elem * &r, int x )
    {
        elem *l2 = nullptr, *r2 = nullptr;
    
        bool success = false;
    
        if ( l != nullptr )
        {
            do 
            {
                int key;
    
                pop_front( key, l, r );
                push_front( key, l2, r2 );
    
                success = key == x;
            } while ( !success && l != nullptr );
        }
    
        while ( l2 != nullptr )
        {
            pop_front( key, l2, r2 );
            push_front( key, l, r );
        }
    
        return success;
    }
    

    这是一个演示程序。

    #include <iostream>
    
    struct elem
    {
        int key; 
        elem *next;
    };
    
    void push_front( int n, elem * &l, elem * &r )
    {
        l = new elem { n, l };
    
        if ( r == nullptr ) r = l;
    }
    
    bool pop_front( int &n, elem * &l, elem * &r )
    { 
        bool success = l != nullptr;
    
        if ( success )
        {
            n = l->key;
    
            elem *tmp = l;
    
            l = l->next;
    
            if ( l == nullptr ) r = nullptr;
    
            delete tmp;
        }
    
        return success;
    }   
    
    
    bool search( elem * &l, elem * &r, int x )
    {
        elem *l2 = nullptr, *r2 = nullptr;
    
        bool success = false;
    
        if ( l != nullptr )
        {
            do 
            {
                int key;
    
                pop_front( key, l, r );
                push_front( key, l2, r2 );
    
                success = key == x;
            } while ( !success && l != nullptr );
        }
    
        while ( l2 != nullptr )
        {
            pop_front( key, l2, r2 );
            push_front( key, l, r );
        }
    
        return success;
    }
    
    int main() 
    {
        elem *left = nullptr, *right = nullptr;
    
        const int N = 10;
    
        for ( int i = N; i != 0; --i )
        {
            push_front( i, left, right );
        }
    
        if ( !search( left, right, 0 ) )
        {
            push_front( 0, left, right );
        }
    
        while ( left != nullptr )
        {
            int key;
    
            pop_front( key, left, right );
    
            std::cout << key << ' ';
        }
    
        std::cout << '\n';
    
        return 0;
    }
    

    它的输出是

    0 1 2 3 4 5 6 7 8 9 10 
    

    也就是说,如果在形成的列表中找不到 0,则将其推到列表的前面。程序输出显示结果。

    【讨论】:

      猜你喜欢
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      • 2021-07-08
      • 2017-01-22
      • 2012-03-19
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多