【问题标题】:How to store value of pointer in a recursive function?如何将指针的值存储在递归函数中?
【发布时间】:2021-08-05 20:00:07
【问题描述】:

现在假设我想编写一个函数,递归地搜索链表中的某个节点。当我成功到达目标节点时,这个函数会通过引用返回它的ID和其他信息,它的ID将通过struct存储:

struct P{
     int ID;
     int some_info;
     P* next_node;
}

函数类似于

void search(int targeted_ID, P*& current_node){
     P* c = current_node;
     if(c->ID == targeted_ID){
           current_node = c;
     }
     if(c->next_node == nullptr){
           return;
     }
     else{
          search(ID, current_node->next_node);
     }
}

输出语句将类似于

cout << "The targeted node have ID= " << current_node->ID << "with" << current_node->some_info << endl;

但是,这个函数会自己递归调用,直到所有节点都到达并检查完,并且指针current_node的值会在整个过程中不断变化。

主要问题是如何在进行递归时保持它的值不变。

附言存在以下限制:

  1. 无法添加任何全局变量
  2. 不能使用任何静态变量
  3. 无法在 void 函数中添加任何参数
  4. 不能使用数组
  5. 无法更改struct 的内容
  6. 输出语句不能更改
  7. 无法使用goto

【问题讨论】:

  • "不能在void函数中添加任何参数"?为什么,为什么不直接返回一个指向找到的节点的指针?

标签: c++ pointers recursion


【解决方案1】:

递归:

void search(int targeted_ID, P*& current_node) {
    if(current_node && current_node->ID != targeted_ID) {
         current_node = current_node->next_node;
         search(targeted_ID, current_node);
    }
}

但我建议使用非递归版本在搜索长链表时不会出现堆栈溢出:

void search(int targeted_ID, P*& current_node) {
    while(current_node && current_node->ID != targeted_ID)
        current_node = current_node->next_node;
}

Demo

【讨论】:

    【解决方案2】:

    正如@Ted Lyngmo 指出的那样,我只是编写了一点代码,你必须返回一个值,所以你不能使用 void 函数。

    代码如下:

    #include <iostream>
    
    struct P {
        int ID;
        int some_info;
        P* next_node;
    };
    
    
    P* newNode(int ID, int some_info) {
        P* temp = new (std::nothrow) P;
    
        if (temp == nullptr){
            return nullptr;
        }
        else {
            temp->ID = ID;
            temp->some_info = some_info;
            temp->next_node = nullptr;
            return temp;
        }
    }
    
    
    P* search(int targeted_ID, P* current_node) {
        // check if current node is valid
        if (current_node == nullptr) {
            return nullptr;
        }
        // check for ID of current node
        else if (current_node->ID == targeted_ID) {
            return current_node;
        }
        // this node isn't the desired one --> go to nex node
        else {
            return search(targeted_ID, current_node->next_node);
        }
    }
    
    
    
    void freeMem(P* list) {
        P* tmp = nullptr;
    
        while (list != nullptr) {
            tmp = list->next_node;
            delete list;
            list = tmp;
        }
    }
    
    
    int main()
    {
        P* list = nullptr;
        P* tmp = nullptr;
        P* lastNode = nullptr;
    
        // populate list
        for (int i = 0; i < 10; ++i) {
            tmp = newNode(i, i * 10);
        
            if (tmp == nullptr) {
                // error occured
                // free memory
                freeMem(list);
                list = nullptr;
                return -1;
            }
    
            if (list == nullptr) {
                // first node
                list = tmp;
                lastNode = list;
            }
            else {
                lastNode->next_node = tmp;
                lastNode = tmp;
            }
        }
    
        tmp = nullptr;
        lastNode = nullptr;
    
        int ID_to_find = 1;
        P* node = search(ID_to_find, list);
    
        if (node == nullptr) {
            // node not found ...
            std::cout << "node not found" << std::endl;
        }
        else {
            // node found
            std::cout << "node found at: " << node << std::endl;
        }
    
    
        freeMem(list);
        list = nullptr;
    
        return 0;
    }
    

    这段代码有效,但它不是真正的 C++,它更像 C。如果你想编写 C++ 代码,请使用 STL-Containers,不要编写自己的列表,因为它更具可读性和出现错误的机会要小得多。还要考虑使用异常而不是(std::nothrow)

    【讨论】:

      猜你喜欢
      • 2019-06-19
      • 1970-01-01
      • 2021-06-03
      • 2016-11-23
      • 2014-06-27
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 2011-04-15
      相关资源
      最近更新 更多