【问题标题】:Using a capacity-constrained queue to list off strings in order?使用容量受限的队列按顺序列出字符串?
【发布时间】:2012-02-09 00:48:35
【问题描述】:

我的教授让我们编写单个 char 队列(没有模板,只有字符),我没有太多麻烦就这样做了。现在我已经用它编写了一个驱动程序(main()),它将打印出序列 ABC 的每个组合。

字符串必须按以下顺序生成:

A
B
C
AA
AB
AC
BA
BB
BC
CA
CB
CC
AAA
AAB
AAC
ABA
ABB
ABC
ACA
ACB
ACC
etc.

队列的 MAX_SIZE = 10,所以它应该在大约 25 个字符串之后抛出溢出异常。

这是提示:

Start with A and B and C in the queue.
“Remove it Display it then Add Add  Add ”

这有点道理,但我不知道如何让主控制结构每次都向上转换一个字符长度(比如一旦它确实所有单个字符都移动到两倍,然后到三倍,等等)。

【问题讨论】:

  • +1 这是一个非常有趣的谜题。即使这不是你的教授想要的,这仍然很酷。
  • 我们可以使用多个队列吗?内存/数据结构使用的限制是什么?
  • 是的,有余地,所以我认为多个队列是可以的。我希望它可能是简单的东西,比如指数公式或模数之类的,但我很难过~_~

标签: c++ string data-structures queue sequence


【解决方案1】:

这是一种解决方案。很简单。

Queue q;

q.enqueue('A');
q.enqueue('\n');
q.enqueue('B');
q.enqueue('\n');
q.enqueue('C');
q.enqueue('\n');

for (size_t i = 0; i < 25; ++i) {
    size_t len = 0;
    char str[256];
    char c;

    while ((c = q.dequeue()) != '\n')
        str[len++] = c;

    str[len] = '\0';

    std::cout << str << std::endl;

    for (size_t j = 0; j < len; ++j)
        q.enqueue(str[j]);

    q.enqueue('A');
    q.enqueue('\n');

    for (size_t j = 0; j < len; ++j)
        q.enqueue(str[j]);

    q.enqueue('B');
    q.enqueue('\n');

    for (size_t j = 0; j < len; ++j)
        q.enqueue(str[j]);

    q.enqueue('C');
    q.enqueue('\n');
}

【讨论】:

  • 我认为这很快就超过了队列内 10 个字符的限制。一次迭代后,它拥有 AnBnCn,即六个字符。之后,它拥有 BnAnAnBnCn,即十个字符。你能在不溢出容量的情况下做到这一点吗?
  • 好吧,完全不用队列也可以做到这一点。但是如果我们需要用它来存储所有的排列,它会变得很大。
  • 是的,但我认为这里的问题是如何仅使用队列来执行此操作。不过,我同意其他生成方法当然值得研究。
【解决方案2】:

首先,让我们注意,如果您有一个字符串队列,这并不是特别困难。一般算法是对字符串图的广度优先搜索:

  1. 创建一个空队列 Q。
  2. 将空字符串插入 Q。
  3. 循环直到完成(您对完成的定义):
    1. 将 Q 的头部出列,称之为 w。
    2. 打印。
    3. 将 wA、wB 和 wC 插入 Q。

问题的关键在于,如果不快速耗尽所有可用空间,就无法将这些字符串插入队列。但是,如果允许使用多个队列,则可以将这些队列链接在一​​起以形成一个更大的队列。例如,假设您有两个容量为 3 的队列,并且想要创建一个容量为 6 的队列。为此,请将队列标记为“左队列”和“右队列”。默认情况下,您插入到正确的队列中,如下所示:

  Left            Right
  [ ] [ ] [ ]     [ ] [ ] [ ]         Enqueue A
  [ ] [ ] [ ]     [ ] [ ] [A]         Enqueue B
  [ ] [ ] [ ]     [ ] [A] [B]         Enqueue C
  [ ] [ ] [ ]     [A] [B] [C]

现在,假设您在正确的队列中用完了空间。在这种情况下,从右队列中取出一个元素(它将是组合队列中最旧的元素),然后将其加入左队列:

  Left            Right
  [ ] [ ] [ ]     [A] [B] [C]         Enqueue D
  [ ] [ ] [A]     [B] [C] [D]         Enqueue E
  [ ] [A] [B]     [C] [D] [E]         Enqueue F
  [A] [B] [C]     [D] [E] [F]

现在,要执行出队操作,请执行以下操作。首先,如果左队列是非空的,从它出列;这让你回到了一堆中最古老的元素。否则,如果正确的队列是非空的,则从那个队列中取出。例如,这里有一些入队和出队:

  Left            Right
  [A] [B] [C]     [D] [E] [F]         Dequeue (yields A)
  [B] [C] [ ]     [D] [E] [F]         Dequeue (yields B)
  [C] [ ] [ ]     [D] [E] [F]         Dequeue (yields C)
  [ ] [ ] [ ]     [D] [E] [F]         Dequeue (yields D)
  [ ] [ ] [ ]     [ ] [E] [F]         Enqueue G
  [ ] [ ] [ ]     [E] [F] [G]         Enqueue H
  [ ] [ ] [E]     [F] [G] [H]         Dequeue (yields E)

您可以通过将多个队列拼接成一个长链来推广这种技术。使用它,您可以将仅包含 10 个字符的小队列组成一个更大的队列,可能容量为 100 或 1000。

那么这有什么帮助呢?好吧,使用链式队列,您可以模拟一个字符串队列!要插入字符串 w,只需将 w 的字符后跟一些标记(例如 $)插入到队列中。例如:

 Long Queue Contents       Operation
 $                         Dequeue once to get $, insert A, B, C
 A$B$C$                    Dequeue twice to get A$, insert AA, AB, AC
 B$C$AA$AB$AC$             Dequeue twice to get B$, insert BA, BB, BC
 C$AA$AB$AC$BA$BB$BC$

等等。使用较小队列的这种组合来模拟模拟字符串队列的较大队列(哇哦!),您可以使用初始算法解决问题。

希望这会有所帮助!

【讨论】:

  • 嗯,这正是我的回答,只是你使用许多队列作为一个队列,其中我不明白这一点。这并不比增加 MAX_SIZE 好。如果这是最好的解决方案,那将是一个非常奇怪的任务。
  • 我发现了一个和我的stackoverflow.com/questions/7437766/…一样的问题
  • 该链接中接受的答案是字符串队列,而不是字符。这是你的吗?
  • 从字面上看是完全相同的问题。教授给了 queue.h 文件,它只是一个 typedef char,所以如果使用字符串它一定是错误的..
  • @rasmus- 我试图使用队列有界的事实来保留正常解决方案的基本 BFS 结构。我根本不认为这是最好的解决方案,但这是一个很酷的思想实验,看看如何从几个较小的队列中模拟一个大队列。另外,这到底是你的答案?我看不到其中的联系,但我真的很感兴趣是否有从一个到另一个的巧妙转换。
【解决方案3】:

仅供参考,这里只使用整数计算。

size_t len = 1;

for (size_t i = 0; i < 5; ++i) {
    size_t x = 0;
    bool max = false;

    do {
        max = true;
        size_t y = x;
        for (size_t j = 0; j < len; ++j) {
            char c = 'A' + (y%3);
            y /= 3;
            if (c != 'C')
                max = false;
            std::cout << c;
        }
        std::cout << std::endl;

        x++;
    } while (!max);
    ++len;
}

【讨论】:

    猜你喜欢
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    相关资源
    最近更新 更多