简体   繁体   English

正确实现单链列表C ++

[英]Correctly implementing a singly linked list C++

I have a list with names of employers such as: 我有一个列出雇主名称的清单,例如:

Node 1: Jill, Matt , Joe, Bob, Matt 节点1:Jill, Matt ,Joe,Bob, Matt

Node 2: Jeff, James, John , Jonathan, John , Edward 节点2:杰夫,詹姆斯, 约翰 ,乔纳森, 约翰 ,爱德华

Node 3: Matt, Doe, Ron , Pablo, Ron , Chase , Ron , Chase, Loui 节点3:Matt,Doe, Ron ,Pablo, RonChaseRon ,Chase,Loui

and I'm trying to get it to where if it sees a repeat it will send it to the front of the list and delete that current node, so that it will look like this 而且我正尝试将其到达重复出现的位置,并将其发送到列表的最前面并删除该当前节点,以使其看起来像这样

Node 1: Matt , Jill, Joe, Bob 节点1: Matt ,Jill,Joe,Bob

Node 2: John , Jeff, James, Jonathan, Edward 节点2: John ,Jeff,James,Jonathan,Edward

Node 3: Chase , Ron , Matt, Doe, Pablo, Loui 节点3: ChaseRon ,Matt,Doe,Pablo,Loui

Unfortunately, My output is close to what I would like. 不幸的是,我的输出接近我想要的。 It's deleting the duplicate entries, but it's not sending to the front. 它正在删除重复的条目,但没有发送到最前面。 .

My output: 我的输出:

Node 1: Jill, Matt , Joe, Bob, 节点1:Jill, Matt ,Joe,Bob,

Well, let's see: 好吧,走着瞧:

When you hit if (ptr->data == p->data) at that point: 当您在此时点击if (ptr->data == p->data)时:

  • pp points to the end of the list pp指向列表的末尾
  • p is you new node (nothing points to it and it points to nothing) p是您的新节点(没有指向它,也没有指向任何东西)
  • ptr points to the node with duplicate data ptr指向具有重复数据的节点

In order to delete the node you need to actually need to have the next pointer pointing to ptr otherwise how can you remove ptr from the list? 为了删除节点,您实际上需要使next指针指向ptr否则如何从列表中删除ptr So you would actually need to check: 因此,您实际上需要检查:

if (head && head->data == p->data)
{
    // do nothing as duplicate entry is already head of list
    delete p;
    return;
}

node *ptr = head;
while (ptr)
{
    if (ptr->next && ptr->next->data == p->data)
    {
        node *duplicate = ptr->next;
        ptr->next = duplicate->next; // skip the duplicate node
        duplicate->next = head;      // duplicate points to head
        head = duplicate;            // head is now the duplicate
        delete p;                    // otherwise leaking memory
        return;
    }
    ptr = ptr->next;
}

if (pp) // points to tail as per your code
{
    pp->next = p;
    ++N;
}

I changed your variable names to be more readable, but kept the forward-declaration in case you wanted it like that. 我将变量名更改为更易读,但保留了前向声明,以防您需要这样的声明。 The issues I found were that you were always inserting the node at the end of the list, regardless of if you found it was a duplicate. 我发现的问题是,您始终将节点插入列表的末尾,无论您是否发现它是重复的。 In addition, your commented lines appeared close, but only if alone. 此外,您的评论行似乎很近,但仅当单独出现时。 With the pp=p stuff, it would cause issues. 使用pp=p东西,会引起问题。 Try the following and see if it works. 请尝试以下操作,看看是否可行。 You'll still be leaking memory, but it will get you started: 您仍然会泄漏内存,但是它将帮助您入门:

void list::put(int i) {  //Where i is a random number
    node *current =head;
    node *added =new node(employers[i]);
    node *tail =head;
    node *prev = NULL;
    bool foundRepeat = false;



    while (current!=NULL)
    {
        if (current->data == added->data)
        {  
            if (prev)
                prev->next = current->next;

            current->next=head;
            head=current;
            foundRepeat = true;
            break;
        }
        prev = current;
        current=current->next;
    }

    if (!foundRepeat)
    {
        while (tail->next) 
        {
            tail=tail->next;
        }
        tail->next=added;
    }

    N++;
}

For what it's worth, I'd probably implement it like this. 对于它的价值,我可能会这样实现。

class EmployerCollection
{
public:
    typedef std::list<std::string> EmployerList;

public:
    bool AddEmployer(const std::string& name)
    {
        EmployerList::const_iterator it = std::find(m_employers.begin(), m_employers.end(), name);
        if (it != m_employers.end()) // Already exists in list.
        {
            m_employers.splice(m_employers.begin(), m_employers, it, std::next(it));
            return true;
        }
        m_employers.push_front(name);
        return false;
    }

private:
    EmployerList m_employers;
};

int main()
{
    const int NUM_EMPLOYERS = 15;
    std::string employers[NUM_EMPLOYERS] = {"Jill", "Jeff", "Doe", "Pablo", "Loui", "Ron", "Bob", "Joe", "Monica", "Luis", "Edward", "Matt", "James", "Edward", "John"};

    EmployerCollection c;

    for (int i=0; i<NUM_EMPLOYERS; i++)
    {
        bool duplicate = c.AddEmployer(employers[i]);
        printf("Added %s to employer list - duplicate: %s \n", employers[i].c_str(), duplicate ? "True" : "False");
    }

    system("pause");
} 

I've added a find function 我添加了查找功能

typedef struct node{
  string data;
  struct node *net, *prev;
 }node;      


class list {
public:
    list():head(NULL), N(0){}
    ~list(){
    //Implementation for cleanup
     }

void add(string name){  //rather than accessing the global data, use the value passed
    node* p = new node(name);
    p->next=p->prev=NULL;
    node* pp = find(name);
    if(pp==NULL){
      // No match found, append to rear
      if(head==NULL)
        head=p;  //list empty, add first element
      else{
        node* cur=head;
        while(cur->next!=NULL) //Keep looking until a slot is found
          cur=cur->next;
        cur->next=p;
        p->prev=cur;
      }
    }
    else{
        //Match found, detach it from its location
        node* pPrev = pp->prev;
        pPrev->next = pp->next;
        pp->next->prev=pPrev;
        p->next = head; //append it to the front & adjust pointers
        head->prev=p;
    }
    N++;
    }

    //MER: finds a matching element and returns the node otherwise returns NULL
    node* find(string name){
        node *cur=head;
        if(cur==NULL) // is it a blank list?
          return NULL;
        else if(cur->data==head) //is first element the same?
          return head;
        else   // Keep looking until the list ends
          while(cur->next!=NULL){
          if(cur->data==name)
            return cur;
            cur=cur->next;
          }
        return NULL;
}
friend ostream& operator << (ostream& os, const list& mylist);

private:
    int N;
    node *head;

};

Now some may tell you to use the list in STL n never to write your own code coz you can't beat STL, but to me it's good that you are implementing your own to get a clear idea on how it works in reality. 现在有些人可能会告诉您使用STL中的列表n永远不要编写您自己的代码,因为您无法击败STL,但是对我来说,很好的是,您正在实现自己的代码,以清楚地了解它在现实中的工作方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM