用于在链表

时间:2018-05-28 12:31:31

标签: c++ data-structures linked-list

用于编写Snode* findset& operator=( set &rhs)的算法是什么我无法理解这两个。我可以阅读代码,但我无法弄清楚它们为什么存在。我无法理解所用算法的步骤。 我已经想到的事情: 1. Snode是一个获取值并返回具有相同数据的节点的函数。但prevprevious做什么以及什么是**previous以及为什么我们要创建一个指向一个指针? 2. set& operator=用于覆盖=运算符。但我无法理解在重写之后它做了什么。为什么我们应该交换headtemp集的rhs。 这是代码:

#include <iostream>
using namespace std;

struct Snode //Snode class defines a node in a list
{
    char data;//a node includes a character
    int count;//an integer to count the occurrence
    Snode *next = NULL;//and a pointer to the next node
    Snode(char data, Snode* next) : data(data), next(next) {}
};

class set
{
private:
    Snode *head;//first node in the list
    Snode *tail;//last node of the list

public:

    set() : head(NULL), tail(NULL)
    {
    }

    set( set &src) : head(NULL), tail(NULL)//copy constructor method
    {
        Snode *temp = src.head;//set head of the second list as temp to travers

        while (temp)//untill the end of the list
        {
            // insert(temp->data);

            Snode *newNode = new Snode(temp->data,NULL);//create a new node with the same data and count
            newNode->count = temp->count;

            //now puts it in the right place
            if (!head)//if head = NULL (if sset is empty)
                head = newNode;//set the new node as the first node

            if (tail)//if tail != NULL (if set isn't empty)
                tail->next = newNode;//set new node as the next node of current tail, so it'll be the tail
            tail = newNode;

            temp = temp->next;//does the same thing for all the nodes of the second list
        }
    }

    ~set()//destructor method
    {
        Snode *temp = head;
        while (temp)//traverse the list and delete each node
        {
            Snode *next = temp->next;
            delete temp;
            temp = next;
        }
    }

    set& operator=( set &rhs)
    {
        if (&rhs != this)
        {
            set temp(rhs);
            Snode *ptr = head;
            head = temp.head;
            temp.head = ptr;
        }
        return *this;
    }

    bool isAvailable(char value)//checks if any node with the same data exists or not
    {
        return (find(value) != NULL);//if find function can't find any, there's no same node
    }

    Snode* find(char value, Snode **previous = NULL)
    {
        if (previous)
            *previous = NULL;

        Snode *temp = head;
        Snode *prev = NULL;

        while (temp)
        {
            if (temp->data == value)
            {
                if (previous)
                    *previous = prev;
                return temp;
            }

            temp = temp->next;
        }

        return NULL;
    }
    bool isFirst(char value)
    {
        return ((head) && (head->data == value));//if head's data is equal to value returns true
    }

    bool isLast(char value)
    {
        return ((tail) && (tail->data == value));//if tail's data is equal to value returns true
    }

    void display()
    {
        Snode *temp = head;
        while (temp)
        {
            cout << temp->data << " " << temp->count+1 << "\n";
            temp = temp->next;
        }
    }

    void insert(char value)//to insert a new value
    {
        Snode *temp = find(value);//if a node with the same data alreay exists
        if (temp)
            temp->count += 1;//increase the count by one
        else
        {
            temp = new Snode(value,NULL);//if if a node with the same data doesn't exist

            if (!head)//if list is empty
                head = temp;

            if (tail)//if list is not empty
                tail->next = temp;
            tail = temp;
        }
    }

    int count(char value)//count the nodes by the counter temp
    {
        Snode *temp = find(value);//travers the set
        return (temp) ? temp->count : 0;//if the list is empty return 0, else return the counter
    }

    void deleteFirst()//deletes the first node
    {
        if (head)//if list isn't empty
        {
            Snode *temp = head;
            head = head->next;//move the head forward
            if (tail == temp)//if loop faced the tail
                tail = NULL;
            delete temp;//delete the data
        }
    }

    void deleteLast()//delete the last node
    {
        if (head)
        {
            Snode *last = head;
            Snode *previous = NULL;

            while (last->next)//move forward untill the node before the last one
            {
                previous = last;
                last = last->next;
            }

            if (previous)//at the end of the list
                previous->next = NULL;
            tail = previous;

            if (head == last)//if there's only one node
                head = NULL;

            delete last;
        }
    }

    void remove(char value)//remove the node with the same data as the entry
    {
        Snode *previous;
        Snode *temp = find(value, &previous);

        if (temp)
        {
            if (temp->count > 1)
                temp->count -= 1;
            else
            {
                if (previous)
                    previous->next = temp->next;

                if (head == temp)
                    head = temp->next;

                if (tail == temp)
                    tail = previous;

                delete temp;
            }
        }
    }   };

1 个答案:

答案 0 :(得分:2)

正如您所猜测的那样,find会尝试找到包含所需字符的Snode。如果只需要,您可以忽略previous参数(它将为NULL),previous / prev处理将无用。

find中使用remove ...为了删除单链表中的节点,您必须将前一个点指向下一个节点。因此,您必须浏览列表跟踪上一个节点。这正是remove中使用的方式:

            if (previous)
                previous->next = temp->next;

赋值运算符使用copy and swap idiom的近似变体。但由于析构函数仅使用head成员,因此只交换该成员:这将足以让temp的析构函数销毁原始列表的所有节点。

即使在tail中设置this无效,也应在tmp中设置set& operator=( set &rhs) { if (&rhs != this) { set temp(rhs); Snode *ptr = head; head = temp.head; temp.head = ptr; tail = temp.tail; // no need for a full swap here } return *this; } 。正确的实施可能是:

sqldeveloper