如何遍历双端队列并搜索元素?

时间:2020-03-25 17:03:23

标签: c++ deque

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

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;

}

感谢您的帮助。 而且也不行,我不能使用双端队列库或std :: find或类似的东西。

2 个答案:

答案 0 :(得分:0)

对于初学者来说,函数push_frontpop_front都有错别字。在函数中,必须使用参数leftright的标识符代替标识符lr

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,它将被推到列表的前面。程序输出显示结果。

答案 1 :(得分:0)

如何遍历双端队列...

这在很大程度上取决于用于实现双头队列的数据结构。例如,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->key;
  • 要移至下一个元素,请执行node = node->next;
  • 要检查迭代器是否相等,请return node == other.node;
  • 表示结束符的迭代器可以表示为nullptr或使用前哨节点。

...并搜索元素?

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