C++ 正确实现单链表C++;
我有一份雇主名单,包括: 节点1:Jill,Matt,Joe,Bob,Matt 节点2:杰夫、詹姆斯、约翰、乔纳森、约翰、爱德华 节点3:Matt,Doe,罗恩,Pablo,罗恩,蔡斯,罗恩,蔡斯,路易 我试着把它放到一个地方,如果它看到一个重复,它会把它发送到列表的前面,并删除当前的节点,这样它就会像这样 节点1:马特、吉尔、乔、鲍勃 节点2:约翰,杰夫,詹姆斯,乔纳森,爱德华 节点3:蔡斯,罗恩,马特,多伊,巴勃罗,路易 不幸的是,我的输出接近我想要的。它正在删除重复条目,但不会发送到前端 我的输出:C++ 正确实现单链表C++;,c++,linked-list,C++,Linked List,我有一份雇主名单,包括: 节点1:Jill,Matt,Joe,Bob,Matt 节点2:杰夫、詹姆斯、约翰、乔纳森、约翰、爱德华 节点3:Matt,Doe,罗恩,Pablo,罗恩,蔡斯,罗恩,蔡斯,路易 我试着把它放到一个地方,如果它看到一个重复,它会把它发送到列表的前面,并删除当前的节点,这样它就会像这样 节点1:马特、吉尔、乔、鲍勃 节点2:约翰,杰夫,詹姆斯,乔纳森,爱德华 节点3:蔡斯,罗恩,马特,多伊,巴勃罗,路易 不幸的是,我的输出接近我想要的。它正在删除重复条目,但不会发送到前端
节点1:Jill,Matt,Joe,Bob,我更改了变量名,使其更具可读性,但保留了转发声明,以防您需要这样做。我发现的问题是,您总是在列表末尾插入节点,而不管您是否发现它是重复的。此外,您的注释行看起来很接近,但只有在单独出现时。对于
pp=p
之类的东西,它会引起问题。试试下面的方法,看看是否有效。您仍然会泄漏内存,但这会让您开始:
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++;
}
好吧,让我们看看:
当您点击if(ptr->data==p->data)
时:
指向列表的末尾pp
是您的新节点(没有指向它,也没有指向它)p
指向具有重复数据的节点ptr
next
指针指向ptr
,否则如何从列表中删除ptr
?因此,您实际上需要检查:
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;
}
无论如何,我可能会这样实现它
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");
}
class EmployeerCollection
{
公众:
typedef std::列出员工列表;
公众:
布尔加法器(常量标准::字符串和名称)
{
EmployerList::const_迭代器it=std::find(m_employers.begin(),m_employers.end(),name);
if(it!=m_employers.end())//已存在于列表中。
{
拼接(m_employers.begin(),m_employers,it,std::next(it));
返回true;
}
m_雇主。推_前线(姓名);
返回false;
}
私人:
雇主主义m_雇主;
};
int main()
{
const int NUM_雇主=15;
字符串雇主[NUM_雇主]={“吉尔”、“杰夫”、“多伊”、“巴勃罗”、“路易”、“罗恩”、“鲍勃”、“乔”、“莫妮卡”、“路易斯”、“爱德华”、“马特”、“詹姆斯”、“爱德华”、“约翰”};
雇主集合c;
对于(inti=0;i我添加了一个find函数
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;
};
typedef结构节点{
字符串数据;
结构节点*net,*prev;
}节点;
班级名单{
公众:
list():head(NULL),N(0){
~list(){
//清理的实现
}
void add(string name){//使用传递的值,而不是访问全局数据
节点*p=新节点(名称);
p->next=p->prev=NULL;
节点*pp=find(名称);
if(pp==NULL){
//未找到匹配项,请附加到后面
if(head==NULL)
head=p;//列表为空,添加第一个元素
否则{
节点*cur=头部;
while(cur->next!=NULL)//继续查找,直到找到插槽
cur=cur->next;
cur->next=p;
p->prev=cur;
}
}
否则{
//找到匹配项,将其从其位置分离
节点*pPrev=pp->prev;
pPrev->next=pp->next;
pp->next->prev=pPrev;
p->next=head;//将其附加到前面并调整指针
头->上一个=p;
}
N++;
}
//MER:查找匹配的元素并返回节点,否则返回NULL
节点*查找(字符串名称){
节点*cur=头部;
if(cur==NULL)//是否为空列表?
返回NULL;
否则如果(cur->data==head)//第一个元素是否相同?
回流头;
else//继续查找,直到列表结束
while(cur->next!=NULL){
如果(当前->数据==名称)
返回电流;
cur=cur->next;
}
返回NULL;
}
friend ostream&operator链表的正确实现方法是std::list
有人知道插入列表前面的正确方法吗?@Mdjon26-您是否参加了相同的课程?添加到列表前面比添加到末尾容易得多。如果您不需要添加末尾,请尝试添加到前面。使用A->B->C
现在添加B
。你将得到一个从A
到B
的圆圈,回到A
并丢失了C
。更不用说内存泄漏了。是的,我不关心内存泄漏。他应该一边处理/一边学习它,尽管我可能应该提到它。你是循环正确,已更新并已修复…最好不要使用常量定义数组的大小NUM_EMPLOYERS
。最好让编译器计算它。然后可以得到NUM_EMPLOYERS
。首选:std::string EMPLOYERS[]={STUFF};
然后const int NUM_EMPLOYERS=sizeof(EMPLOYERS)/sizeof(employers[0]);
我真的看不出有什么区别,它纯粹是为了示例而使用的,并且在循环过程中使用了一个变量。首先,这里有一个手写字符串数组的事实违背了整个练习的目的。