【问题标题】:Detecting Duplicates With a Linked List使用链表检测重复项
【发布时间】:2021-01-02 13:20:01
【问题描述】:

我正在尝试转换可以检测重复字符串并抛出错误的数组集算法,但这次我尝试使用链接集来实现它,而不是在数组集中进行。任何指导将不胜感激。

这是我在数组集中使用时的函数:

template<class ItemType>
void ArraySet<ItemType>::add(const ItemType& newEntry) {
    if (std::find(std::begin(items), std::end(items), newEntry) != std::end(items))
    {
        throw DuplicateItemError(); 
    }  
    else 
    {  
        items[itemCount] = newEntry;
        itemCount++;
    }  
}  

这是我未修改的 Linked Set 函数,我试图将相同的逻辑应用于但不同:

template<class ItemType>
void LinkedSet<ItemType>::add(const ItemType& newEntry) {
    Node<ItemType>* nextNodePtr = new Node<ItemType>();
    nextNodePtr->setItem(newEntry);
    nextNodePtr->setNext(headPtr);

    headPtr = nextNodePtr;          // New node is now first node
    itemCount++;
}

这里也是类文件:

#ifndef LINKED_SET_
#define LINKED_SET_

#include "SetInterface.h"
#include "Node.h"

namespace cs_set {

    template<class ItemType>
    class LinkedSet : public SetInterface<ItemType>
    {
        private:
            Node<ItemType>* headPtr;
            int itemCount;

            // Returns either a pointer to the node containing a given entry
            // or nullptr if the entry is not in the bag.
            Node<ItemType>* getPointerTo(const ItemType& target) const;
   
        public:
            class ItemNotFoundError {};
            class DuplicateItemError {};
            LinkedSet();
            LinkedSet(const LinkedSet<ItemType>& aSet);
            virtual ~LinkedSet();
            int getCurrentSize() const;
            bool isEmpty() const;
            void add(const ItemType& newEntry);
            void remove(const ItemType& anEntry);
            void clear();
            bool contains(const ItemType& anEntry) const;
            //int getFrequencyOf(const ItemType& anEntry) const;
            std::vector<ItemType> toVector() const;
    };
}

#include "LinkedSet.cpp"
#endif 

设置接口文件:

#ifndef SET_INTERFACE
#define SET_INTERFACE

#include <vector>
#include <algorithm>
#include <iterator>

namespace cs_set {
    template<class ItemType>
    class SetInterface
    {
        public:
           /** Gets the current number of entries in this bag.
            @return  The integer number of entries currently in the set. */
           virtual int getCurrentSize() const = 0;
   
           /** Sees whether this set is empty.
            @return  True if the set is empty, or false if not. */
           virtual bool isEmpty() const = 0;
   
           /** Adds a new entry to this set.
            @post  If successful, newEntry is stored in the set and
               the count of items in the set has increased by 1.
            @param newEntry  The object to be added as a new entry.
            @return  True if addition was successful, or false if not. */
           virtual void add(const ItemType& newEntry) = 0;
   
           /** Removes one occurrence of a given entry from this set,
               if possible.
            @post  If successful, anEntry has been removed from the set
               and the count of items in the bag has decreased by 1.
            @param anEntry  The entry to be removed.
            @return  True if removal was successful, or false if not. */
           virtual void remove(const ItemType& anEntry) = 0;
   
           /** Removes all entries from this set.
            @post  set contains no items, and the count of items is 0. */
           virtual void clear() = 0;
   
           /** Counts the number of times a given entry appears in this set.
            @param anEntry  The entry to be counted.
            @return  The number of times anEntry appears in the set. */
          // virtual int getFrequencyOf(const ItemType& anEntry) const = 0;
   
           /** Tests whether this set contains a given entry.
            @param anEntry  The entry to locate.
            @return  True if bag contains anEntry, or false otherwise. */
           virtual bool contains(const ItemType& anEntry) const = 0;
   
           /** Empties and then fills a given vector with all entries that
               are in this set.
            @return  A vector containing all the entries in the bag. */
           virtual std::vector<ItemType> toVector() const = 0;
   
           /** Destroys this set and frees its assigned memory. (See C++ Interlude 2.) */
           virtual ~SetInterface() { }
    };
}
#endif

【问题讨论】:

  • SetInterface&lt;ItemType&gt; -- 什么是SetInterface?为什么你写的内容与简单地使用 std::forward_list&lt;ItemType&gt; 有什么不同?
  • SetInterface 是我的主要类,我忘了包含它
  • 遍历列表并与要添加的项目进行比较。如果发现重复,请勿添加。
  • 如果您在链接列表中正确设置了begin()end(),那么它的工作原理应该基本相同。您只需通过它运行find(),如果没有重复则添加元素
  • ArraySet 代码表明items 是一个固定长度的数组。如果是这样,那么使用std::end(items)是错误的,应该是std::begin(items)+itemCount,否则还会比较未分配的元素,可能会导致意想不到的结果。

标签: c++ class exception linked-list


【解决方案1】:

就像使用数组一样,您需要迭代链表以查找重复元素。

如果您为您的LinkedSet 实现了std::begin()std::end(),您可以像使用ArraySet 一样简单地使用std::find()(这就是为什么标准算法被设计为使用迭代器来操作开头),例如:

template<class ItemType>
void LinkedSet<ItemType>::add(const ItemType& newEntry)
{
    if (std::find(std::begin(nodes), std::end(nodes), newEntry) != std::end(nodes))
    {
        throw DuplicateItemError(); 
    }  

    Node<ItemType>* nextNodePtr = new Node<ItemType>();
    nextNodePtr->setItem(newEntry);
    nextNodePtr->setNext(headPtr);

    headPtr = nextNodePtr;          // New node is now first node
    ++itemCount;
}  

否则,如果您没有实现begin()/end(),则可以直接迭代节点,例如:

template<class ItemType>
void LinkedSet<ItemType>::add(const ItemType& newEntry)
{
    for(Node<ItemType>* nodePtr = headPtr; nodePtr; nodePtr = nodePtr->getNext())
    {
        if (nodePtr->getItem() == newEntry)
            throw DuplicateItemError(); 
    }

    Node<ItemType>* nextNodePtr = new Node<ItemType>();
    nextNodePtr->setItem(newEntry);
    nextNodePtr->setNext(headPtr);

    headPtr = nextNodePtr;          // New node is now first node
    ++itemCount;
}

【讨论】:

    猜你喜欢
    • 2021-11-02
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 2017-08-07
    • 1970-01-01
    • 2023-04-02
    相关资源
    最近更新 更多