我有一个链表定义为

struct Node{
   int data;
   Node *next;
};

struct LinkedList{
   Node *head;
};

我想递归地浏览我的链表,并删除具有指定数据类型的节点(并正确地重新加入节点)。 我想出了如何迭代地执行此操作,但是我一直在递归地执行此操作。这是我到目前为止所获得的:

void deleteNodeRecursively(LinkedList* list, int value){
 if (list->head==NULL){
  return;
 } else if (list->head->data==value){
  list->head=list->head->next;
  deleteNodeRecursively(list,value);
 } else {

 }
}

基本上,我的策略是确定磁头是否具有数据。 如果是这样,那么我只需将头替换为下一个节点即可。 问题是我的else语句,在那我知道必须“继续”到下一个节点。 我不仅必须继续前进到下一个节点,而且必须确保它处于LinkedList格式,这样我才能正确使用头。 我不删除所有列表,不知道如何继续。 我有复制的模糊想法吗? 我不太确定现在该怎么办。

编辑:我不想编辑结构定义,因为我将它们用于其他程序。

#1楼 票数:1

有很多方法可以做。

我个人遵循一种简单的方法,即在调用递归函数之前处理签入操作。

if(list->head->data == value)
{
    Node* temp = list->head;
    list->head = list->head->next;
    delete temp;
}
if(list->head != null)
    deleteNodeRecursively(list->head,list->head->next,value);

您的递归函数应该像

void deleteNodeRecursively(Node* parent, Node* child, int value){
if (child == NULL){ // if null that means end of the list
    return;
}
if( child->data == value)
{
    parent->next = child->next; // attach the parent with the next of child. Thus removes the child form the list
    delete child; // clear the dynamically allocated memory
    deleteNodeRecursively(parent,parent->next,value);
}
else
    deleteNodeRecursively(child,child->next,value); // move to the next
}

其他如果可以避免递归,请避免递归。 因为如果列表足够长,它将在到达末尾之前耗尽您的全部堆栈内存。

#2楼 票数:0

我正在努力递归地执行此操作。 我的策略是确定负责人是否有数据

一个很好的策略,类似于MASh的建议,下面是我的努力。

也许以下removeR()方法将有助于完成您的工作。

在此示例中,我没有提供“尾递归”。 以下方法是我的“传统”方法,即简单的实现。 (最近,我发现我很少使用列表,而是更喜欢std :: vector。)


环境:

旧版Dell上的Ubuntu 15.10(64位),

g ++-5(Ubuntu 5.2.1-23ubuntu1〜15.10)5.2.1 20151028


码:

#include <chrono>
// 'compressed' chrono access --------------vvvvvvv
typedef std::chrono::high_resolution_clock  HRClk_t; // std-chrono-hi-res-clk
typedef HRClk_t::time_point                 Time_t;  // std-chrono-hi-res-clk-time-point
typedef std::chrono::milliseconds           MS_t;    // std-chrono-milliseconds
typedef std::chrono::microseconds           US_t;    // std-chrono-microseconds
typedef std::chrono::nanoseconds            NS_t;    // std-chrono-nanoseconds
using   namespace std::chrono_literals;          // support suffixes like 100ms, 2s, 30us
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cassert>


class Node_t
{
private:
   size_t   m_id;    // node indx
   int      m_data;
   Node_t*  m_next;

   static size_t M_id;

public:
   Node_t() = delete;  // disallow default ctor

   Node_t(int d) : m_id(++M_id) , m_data(d) , m_next(nullptr) { }

   ~Node_t() { std::cout << "  ~Node_t() " << show() << std::endl; }

   void appendR(Node_t* n)
      {
         if(m_next) m_next->appendR(n); // spin to end of list
         else       m_next = n;         // append to end
      }

   bool dataMatch(int v) { return (m_data == v); }
   Node_t* next() { return (m_next); }

   // when m_next->m_data matches v,  returns true, else false
   bool removeR(int v);

   std::string showR()
      {
         std::string s = show();
         if(m_next)
            s += m_next->showR(); // spin to end of list
         return (s);
      }

   std::string show()
      {
         std::stringstream ss;
         if (false) ss << "[" << std::to_string(m_id)   << "]";  // node indx
         if (false)  ss << std::to_string(m_id)   << ":";  // node indx
         ss  <<                  std::to_string(m_data) << "  ";
         return ss.str();
      }

   size_t size() {
      size_t retVal = 1;
      if (m_next) { retVal += m_next->size(); } // spin to end of list
      return retVal;
   }

}; // class Node_t

size_t Node_t::M_id = 0; // unique id for each node

class LinkedList_t
{
private:
   Node_t* m_head;

public:
   LinkedList_t() : m_head (nullptr) { }
   ~LinkedList_t() = default;

   void append(Node_t* n)
      {
         assert(n);
         if (nullptr == m_head) m_head = n;
         else                   m_head->appendR(n);
      }

   void removeR(int v);

   std::string show()
      {
         std::string s("ll is empty");
         if(m_head)
            s = m_head->showR();
         return (s);
      }

   size_t size() {
      size_t retVal = 0;
      if (m_head) retVal += m_head->size();
      return retVal;
   }

}; // class LinkedList_t


void LinkedList_t::removeR(int v)
{
   if(nullptr == m_head) // empty list check
   {
      std::cout << "\n  empty" << std::endl;
      return;
   }

   if(m_head->dataMatch(v))      // check data at head
   {
      Node_t* tmp = m_head;
      m_head      = tmp->next(); // unlink prev head
      delete  tmp;
      removeR(v);                // local recursion... node 2 might also contain v
   }

   // not empty && data at head not v then use node recursion
   if(m_head)  (void)m_head->removeR(v);
}

bool Node_t::removeR(int v)
{
   bool  match = false;
   if (m_next) match = m_next->removeR(v); // spin to end of list

   // during decurse
   if(match) // m_next->data matches v
   {
      Node_t* matchNode = m_next;  // node-to-remove
      m_next = m_next->m_next;     // remove link to node-to-remove
      delete matchNode;            // remove node
   }
   // else no remove to do

   return (m_data == v);  // continue decurse, checking for another  match
}


class T516_t
{
private:
   LinkedList_t m_ll;

public:

   T516_t() = default;
   ~T516_t() = default;

   int exec()
      {
         show("m_ll.show().1");

         std::cout << "\n  m_ll.size() = " << m_ll.size() << std::endl;

         for(int i=0; i<6; ++i)
         {
            Node_t* n = new Node_t(i+10); assert(n); // 10..15
            m_ll.append(n);
         }
         for(int i=0; i<6; ++i)
         {
            Node_t* n = new Node_t(i+10); assert(n); // 10..15
            m_ll.append(n);
         };

         show("m_ll.show().2");

         std::cout << "\n  m_ll.size() = " << m_ll.size() << std::endl;

         show("remove(15)");
         m_ll.removeR(15);

         show("m_ll.show().3");

         show("remove(10)");
         m_ll.removeR(10);

         show("m_ll.show().z");

         for (int i=0; i<6;++i)
         {
            std::cout << "\n  remove(" << i+10 << ")    " << std::endl;
            m_ll.removeR(i+10);

            show("m_ll.show()...");
         }

         return(0);
      }

private:

   void show(std::string lbl) {
      std::cout << "\n  " << lbl
                << "  sz:"   << m_ll.size()
                << "   "  << m_ll.show() << std::endl;
   }

}; // class T516_t


int main(int , char** )
{
   Time_t start_us = HRClk_t::now();

   int retVal = -1;
   {
      T516_t   t516;
      retVal = t516.exec();
   }

   auto  duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);

   std::cout << "\n\n  FINI   " << duration_us.count() << " us" << std::endl;
   return(retVal);
}

结果:

R02: dumy524.cc
rm -f dumy524
g++-5 -m64  -O3 -ggdb -std=c++14 -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wcast-align -Wcast-qual -Wconversion -Wpointer-arith -Wunused -Woverloaded-virtual   -O0   dumy524.cc  -o dumy524  -L../../bag -lbag_i686

real    0m1.065s
user    0m0.920s
sys 0m0.100s

  m_ll.show().1  sz:0   ll is empty

  m_ll.size() = 0

  m_ll.show().2  sz:12   10  11  12  13  14  15  10  11  12  13  14  15  

  m_ll.size() = 12

  remove(15)  sz:12   10  11  12  13  14  15  10  11  12  13  14  15  
  ~Node_t() 15  
  ~Node_t() 15  

  m_ll.show().3  sz:10   10  11  12  13  14  10  11  12  13  14  

  remove(10)  sz:10   10  11  12  13  14  10  11  12  13  14  
  ~Node_t() 10  
  ~Node_t() 10  

  m_ll.show().z  sz:8   11  12  13  14  11  12  13  14  

  remove(10)    

  m_ll.show()...  sz:8   11  12  13  14  11  12  13  14  

  remove(11)    
  ~Node_t() 11  
  ~Node_t() 11  

  m_ll.show()...  sz:6   12  13  14  12  13  14  

  remove(12)    
  ~Node_t() 12  
  ~Node_t() 12  

  m_ll.show()...  sz:4   13  14  13  14  

  remove(13)    
  ~Node_t() 13  
  ~Node_t() 13  

  m_ll.show()...  sz:2   14  14  

  remove(14)    
  ~Node_t() 14  
  ~Node_t() 14  

  empty

  m_ll.show()...  sz:0   ll is empty

  remove(15)    

  empty

  m_ll.show()...  sz:0   ll is empty


  FINI   591 us

  ask by Ayumu Kasugano translate from so

未解决问题?本站智能推荐:

1回复

从链表中递归删除节点

给定一个链表和一个指定的数据值,我想递归删除所有具有上述数据的节点。 (我已经想出了如何迭代的方式,但是我想用这种方式)。 我将结构定义为: 为了进行删除,我创建了此辅助函数,该函数(应该)将指针返回到已删除列表的头节点: 然后我要在实际列表中使用它: 但这是行不通的。 看来我
1回复

从递归管理的链表类中删除ch

我构建了while循环,以从链表中删除与给定var相匹配的ch。 我遍历列表,然后删除。 我想通过递归而不是迭代来管理它。 我对语法一无所知。 以前从未做过递归。 在标题中... 在源码中使用迭代
2回复

如何使用C++递归查找链表中数据的索引?

本质上,要搜索的列表和元素被传递给函数。 该函数应该返回元素在列表中的位置。 我附上了我尝试过的东西。 在调用此函数时有 11 个元素的测试程序中,如果元素在列表中,则结果始终为 1,如果不在列表中,则正确返回 -1。
4回复

在链表中递归查找最低编号

我试图在我创建的链表中找到最低的值,我需要递归地找到它,有关如何执行此操作的任何想法? 这是我头的东西
3回复

在链表中查找值的递归方法

该函数应该找到所搜索的值并返回该特定值在链表中的次数。 如何将使用while循环的第一种方法转换为执行相同操作但使用递归的方法?
1回复

递归链表和C++中的分段错误

这是我使用递归求和的部分代码,但我遇到了分段错误。 看起来问题是如何退出; 但是,我想不通。 私人课堂
2回复

C++:这是以递归方式删除链表的正确方法吗?

我想知道这是否正确,因为XCode在执行getNext()时给出了EXC_BAD_ACCESS错误,但Visual Studio没有。
1回复

递归地在链表中的第i个位置插入节点

将帮助我解决这个问题我正在尝试使用递归在链表中的第 i 个位置插入节点这是代码,请帮助我改进代码,当我必须返回头部时,我最终会特别面临问题,但我不知道如何返回