使用线性搜索为二维数组生成唯一数字

Posted

技术标签:

【中文标题】使用线性搜索为二维数组生成唯一数字【英文标题】:generate unique numbers to 2-Dimensional array using linear search 【发布时间】:2016-12-11 03:06:57 【问题描述】:

程序编译,我可以输入一个数字,但它不生成或显示数组。当我在 randomFillUnique 函数中使用线性搜索取出 while 条件时,它会生成并显示数组,但不是唯一的数字。我需要一个没有重复数字的二维数组。

#include <iostream>
#include <string>
#include <random>
#include <ctime>
using namespace std;

int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);

int main()

    int number;
    cout << "Enter a number: ";
    cin >> number;
    randomFillUnique(gen2Array(number), number);
    system("pause");
    return 0;

int** gen2Array(int n)

    int** arr2D = new int*[n];
    for (int index = 0; index < n; index++)
        arr2D[index] = new int[n];
    return arr2D;

void randomFillUnique(int** arr, int n)

    static default_random_engine e;
    uniform_int_distribution<int> u(1, n*n);
    e.seed(static_cast<int>(time(NULL)));

    bool result = false;
    for (int row = 0; row < n; row++)
    
        for (int col = 0; col < n; col++)
        
            arr[row][col] = u(e);   //generate random number
            result = lSearch(arr, n, arr[row][col]);
            while (result == true)
            
                arr[row][col] = u(e);   //generate random number
                result = lSearch(arr, n, arr[row][col]);
            
        
    
    display(arr, n);
    delete[] arr;

bool lSearch(int** arr, int n, int target)

    bool found = false;
    for (int row = 0; row < n; row++)
        for (int col = 0; col < n; col++)
        
            if (arr[row][col] == target)
            
                found = true;
                return found;
            
        
    return found;

void display(int** arr, int n)

    for (int row = 0; row < n; row++)
    
        for (int col = 0; col < n; col++)
            cout << arr[row][col];
        cout << endl;
    

【问题讨论】:

因为您将 arr[row,col] 设置为 u(e),它总是会在数组中找到该值,而您在 lsearch 中的 while 循环会永远循环 与其随机选择一个数字并拒绝重复,不如考虑在一组可能性中创建一个std::vector,然后应用std::shuffle 来随机化vector。然后从vector中挑选前N个元素 离题:内存泄漏。 delete[] arr; 删除外部数组但不删除内部数组。现在没有任何东西指向内部数组,因此它们非常难以删除。 @user4581301 谢谢你,但是对于这个任务,我的任务是用默认的 void randomFillUnique(int** arr, int n) 随机填充数组。感谢您的内存泄漏建议。我会马上解决的。 知道了。将做出解释技术的答案。使用它可能会惹恼您的讲师,这取决于讲师,这可能是值得的。 【参考方案1】:

因为您在 lsearch 之前将数组中的条目设置为 u(e),所以 lsearch 始终返回 true,而您的 while 将永远循环。以下内容改编自您的代码,应该可以解决这个问题(我假设其余代码的行为与预期的一样)。正如 user4581301 指出的那样,可能有更好的方法,但我希望你的方法足以让它发挥作用。

void randomFillUnique(int** arr, int n)

static default_random_engine e;
uniform_int_distribution<int> u(1, n*n);
e.seed(static_cast<int>(time(NULL)));
int nextEntry;
bool result = false;
for (int row = 0; row < n; row++)

    for (int col = 0; col < n; col++)
    
        result = true;
        while (result == true)
        
            nextEntry = u(e);   //generate random number
            result = lSearch(arr, n, nextEntry);
            if (result != true)
               arr[row][col]=nextEntry;
        
    

display(arr, n);
delete[] arr;

【讨论】:

非常感谢您的帮助。现在可以了。我打算尝试放置一个临时变量,但你为我做了。再次感谢您 你打赌。顺便说一句,我很确定 while (result == true) 可以只说 while (result),而我的 if (result!=true) 可以只说 if (!(result)) 或即使 (!result) 【参考方案2】:

另一种方法是使用iota 创建一个包含所有将进入数组的唯一整数的容器:

std::vector<int> invalues(n*n, 0);
std::iota(invalues.begin(), invalues.end(), 1);

然后随机播放该容器:

std::shuffle(invalues.begin(), invalues.end(),
             std::mt19937std::random_device());

然后将值一一输入到矩阵中。

您也可以使用vector&lt;vector&lt;int&gt;&gt; 代替内置数组:

using matrix = std::vector<std::vector<int>>;

// initialising a vector<vector<int>> to be a certain size is a bit clumsy
matrix m(size_y, std::vector<int>(size_x, 0));

然后将输入值输入矩阵:

for (auto &row : m) 
  for (auto &elem : row) 
    elem = invalues.back();
    invalues.pop_back();
  

然后显示矩阵:

for (const auto &row : m) 
  for (const auto &elem : row) 
    std::cout << elem << " ";
  
  std::cout << std::endl;

Here's a full example in an online compiler.

【讨论】:

谢谢你。我很感激【参考方案3】:

好的。这是我评论过的更简单的方法。如果 std::vector 不被允许,一个简单的一维向量就足够了,但是一个理智的软件工程师会在选择它而不是 vector 之前非常非常努力地思考。

我进行了一些其他更改以修复其他几个错误。

#include <iostream>
#include <string>
#include <random>
#include <vector>
#include <algorithm> // std::shuffle and std::iota
#include <ctime>
using namespace std;

int** gen2Array(int n);
void randomFillUnique(int** arr, int n);
bool lSearch(int** arr, int n, int target);
void display(int** arr, int n);
//Added to properly delete the 2dArray
void del2Array(int ** arr, int n);

int main()

    int number = 10;
    randomFillUnique(gen2Array(number), number);
    system("pause");
    return 0;

int** gen2Array(int n)

    int** arr2D = new int*[n];
    for (int index = 0; index < n; index++)
        arr2D[index] = new int[n];
    return arr2D;


//Added to properly delete the 2dArray
void del2Array(int ** arr,
               int n)

    for (int index = 0; index < n; index++)
        delete arr[index];
    delete arr;

void randomFillUnique(int** arr, int n)

    //do the seeding here
    static default_random_engine e(static_cast<int>(time(NULL)));
// otherwise
//    e.seed(static_cast<int>(time(NULL)));
// runs every time reseeding the RNG to potentially the give the same results
// if run more than once in a second. Plus the seeding is expensive.

    std::vector<int> v(n*n); // make and size vector
    std::iota (v.begin(), v.end(), 0); // init vector with 1 through n*n
    std::shuffle(v.begin(), v.end(), e);

    size_t index = 0;
    for (int row = 0; row < n; row++)
    
        for (int col = 0; col < n; col++)
        
            arr[row][col] = v[index++];   //generate random number
        
    
    display(arr, n);
    del2Array (arr, n); // frankly I don't think you want his here
                        // why fill an array only to delete it?
                        // more logical to display and delete back in main.


void display(int** arr, int n)

    for (int row = 0; row < n; row++)
    
        for (int col = 0; col < n; col++)
            cout << arr[row][col] << "\t"; //added a tab to make the printing easier to read
        cout << endl;
    

Documentation on std::vector

Documentation on std::shuffle

Documentation on std::iota. 正是使用这种技术来演示iota。好笑吧?

【讨论】:

感谢所有帮助和建议。我会注意的。

以上是关于使用线性搜索为二维数组生成唯一数字的主要内容,如果未能解决你的问题,请参考以下文章

在二维数组中创建线性渐变

回溯法计算二维数组最短路径

跨多个单元格最有效地搜索二维数字数组

经典面试算法题:线性查找有序二维数组

如何在从左到右和从上到下排序的二维数组中搜索数字?

C 语言数组 ( 验证二维数组内存是线性的 | 打印二维数组 | 以一维数组方式打印二维数组 | 打印二维数组值和地址 )