通过节点计算单链表中的出现次数

时间:2018-05-19 21:05:00

标签: c++ algorithm c++11 data-structures singly-linked-list

我正在编写一个获得list的简单应用,并将对象保存为<{em>单链表中的nodes,我们可以add(),{{ 1}},remove()等每个节点取决于给定的数据集。每个节点都有copy()这是我们的数据,char value计算相关int count的出现次数。

e.g。对于像

这样的列表
  

a,a,b,b,c,a

将有三个节点(因为有三个不同的字符):

  

char

[a,3,*next] -> [b,2,*next] -> [c,1,*next] -> nullptr检查数据是否已经在列表中。

问:插入数据时有两个选项:

  1. 尚未输入数据:因此我们必须使用给定数据bool isAvailable()newNode创建count=1

  2. 已输入数据:因此我们必须*next=NULL具有相同数据的节点。

  3. 我知道给定数据是否可用,但如何指向具有相同数据的节点?

    以下是代码:

    count++

2 个答案:

答案 0 :(得分:2)

  

我知道给定数据是否可用,但如何指向具有相同数据的节点?

您需要从列表的开头开始,按照next指针迭代列表,直到找到具有相同data值的节点。完成后,您将指向具有相同数据的节点。

其他一些注意事项:

bool set::isAvailable(char value)
{
   Snode *floatingNode = new Snode(char d, int c);
   while(floatingNode != NULL)
   {
       return (value == floatingNode);
       floatingNode->next = floatingNode;
   }
}
  1. 为什么这个函数会分配new Snode?没有理由这样做,只需将floatingNode指针初始化为指向head

  2. 此功能始终仅在查看链接列表中的第一个节点后返回 - 这不是您想要的行为。相反,它应该仅在(value == floatingNode);否则它应该留在while循环中,以便它可以继续查看后续节点。只有在它退出while循环之后(因为floatingNode最终变为NULL)才会返回false。

  3. 如果您稍微修改isAvailable(),以便返回truefalse,而不是返回floatingPointerNULL。 #39; d具有查找指向具有匹配数据的节点的指针的机制。

  4. e.g:

    // Should return either a pointer to the Snode with data==value,
    // or NULL if no such Snode is present in the list 
    Snode * set::getNodeWithValueOrNullIfNotFound(char value) const
    {
       [...]
    }
    
    void set::insert(char value)
    {
       Snode * theNode = getNodeWithValueOrNullIfNotFound(value);
       if (theNode != NULL)
       {
          theNode->count++;
       }
       else
       {
          [create a new Snode and insert it]
       }
    }
    

答案 1 :(得分:1)

您的代码中存在很多问题,让我们看看它们是什么:

  1. 首先,Snode不一定是class,而是可以使用简单strcut;因为我们需要一切public。(不是错误,而是良好做法)
  2. 您可以简单地初始化count = 1next = nullptr,这样就不需要初始化它们抛出构造函数。需要通过构造函数初始化的唯一元素是Snod的data
  3. c++11开始,您可以使用关键字nullptr代替NULL,表示pointer literal
  4. 会员功能bool set::isAvailable(char value)无法正常运作。在这里你不必要地创建了一个new Snode,并且不知道它是否指向nullptr,它不允许你甚至进入循环。 BTW你在循环中写的也错了。你return (value == floatingNode);是什么意思? floatingNode类型为Snode;不是char
  5. 听到正确的实施方式。由于我们不想覆盖头部,因此将创建一个Node*指针并为其指定head。然后遍历列表直到找到匹配项。如果找不到,我们将到达isAvailable()的末尾并返回false

         inline bool isAvailable(const char& value)
         {
             Node *findPos = head;
    
             while(findPos != nullptr)
             {
                 if(findPos -> data == value) return true;
                 else findPos = findPos->next_node;
             }
             return false;
         }
    
    1. void set::insert(char value)中,您的逻辑是正确的,但实施是错误的。以下是正确的实施。(希望评论能帮助您理解。
    2. void insert(const char& value)
      {
          if(head == nullptr) // first case
          {
              Node *newNode = new Node(value);
              newNode->next_node = head;
              head = newNode;
          }
          else if(isAvailable(value)) // if node available
          {
              Node *temp = head;
              while(temp->data != value)  // find the node
                  temp = temp->next_node;
              temp->count += 1;           // and count it by 1
          }
          else                            // all new nodes
          {
              Node *temp = head;
              while(temp->next_node != nullptr) // to find the null point (end of list)
                  temp = temp->next_node;
      
              temp = temp->next_node = new Node(value); // create a node and assign there
          }
      }
      
      1. 您的析构函数不会删除您创建的所有内容。它将是UB,因为您正在删除新创建的Snode t(即Snode *t = head;)。正确的实现如下所示。(取消注释调试消息以理解。)
      2.    ~set()
            {
                Node* temp = head;
                while( temp != nullptr )
                {
                    Node* next = temp->next_node;
                    //std::cout << "deleting \t" << temp->data << std::endl;
                    delete temp;
                    temp = next;
                }
                head = nullptr;
            }
        

        最后但并非最不重要的是,命名(set)你在这里所拥有的以及代码正在做什么都是不同的。这看起来更像是一个没有重复的简单链接列表。然而,这是好的,以便使用指针和列表。

        为了使代码或迭代更有效,您可以执行以下操作。在isAvailable()中,如果值匹配/如果找到node,您也可以简单地增加其计数。然后在insert()中,如果node 不是可用部分,您可以想到。

        希望这有用。查看DEMO

        #include <iostream>
        
        // since you wanna have all of Node in public, declare as struct
        struct Node
        {
            char data;
            int count = 1;
            Node*  next_node = nullptr;
            Node(const char& a) // create a constrcor which will initilize data
                : data(a) {}    // at the time of Node creation
        };
        
        class set
        {
        private:
            Node *head;             // need only head, if it's a simple list
        public:
            set()   :head(nullptr) {}   // constructor set it to nullptr
            ~set()
            {
                Node* temp = head;
                while( temp != nullptr )
                {
                    Node* next = temp->next_node;
                    //std::cout << "deleting \t" << temp->data << std::endl;
                    delete temp;
                    temp = next;
                }
                head = nullptr;
            }
        
            inline bool isAvailable(const char& value)
            {
                Node *findPos = head;
        
                while(findPos != nullptr)
                {
                    if(findPos -> data == value) return true;
                    else findPos = findPos->next_node;
                }
                return false;
            }
        
            void insert(const char& value)
            {
                if(head == nullptr) // first case
                {
                    Node *newNode = new Node(value);
                    newNode->next_node = head;
                    head = newNode;
                }
                else if(isAvailable(value)) // if node available
                {
                    Node *temp = head;
                    while(temp->data != value)  // find the node
                        temp = temp->next_node;
                    temp->count += 1;           // and count it by 1
                }
                else                            // all new nodes
                {
                    Node *temp = head;
                    while(temp->next_node != nullptr) // to find the null point (end of list)
                        temp = temp->next_node;
        
                    temp = temp->next_node = new Node(value);
                }
            }
        
            void print() const      // just to print
            {
                Node *temp = head;
                while(temp != nullptr)
                {
                    std::cout << temp->data << " " << temp->count << "\n";
                    temp = temp->next_node;
                }
            }
        };
        
        
        int main()
        {
            ::set mySet;
        
            mySet.insert('a');
            mySet.insert('a');
            mySet.insert('b');
            mySet.insert('b');
            mySet.insert('c');
            mySet.insert('a');
        
            mySet.print();
        
            return 0;
        }