C 我有一个链表,我想删除重复的值
所以,我创建了一个代码,它创建了一个包含5个值的链表。我想知道什么是最好的方法来删除这些值的重复项,并在没有重复项的情况下再次打印链接列表C 我有一个链表,我想删除重复的值,c,algorithm,struct,linked-list,singly-linked-list,C,Algorithm,Struct,Linked List,Singly Linked List,所以,我创建了一个代码,它创建了一个包含5个值的链表。我想知道什么是最好的方法来删除这些值的重复项,并在没有重复项的情况下再次打印链接列表 #include <stdio.h> #include <stdlib.h> /* self-referential structure*/ struct studentID{ int value; //a data member which is an integer struct student
#include <stdio.h>
#include <stdlib.h>
/* self-referential structure*/
struct studentID{
int value; //a data member which is an integer
struct studentID *next; //a data member which is a pointer to next node
};
typedef struct studentID STUDENTID; //creating a nickname for struct studentID as STUDENTID
typedef STUDENTID *STUDENTIDPtr; //creating a nickname for STUDENTID as STUDENTIDPtr
//Global variables
STUDENTIDPtr previousPtr; //pointer to previous node in list
STUDENTIDPtr currentPtr; //pointer to current node in list
void printList(STUDENTIDPtr currentPtr){
while (currentPtr != NULL){ //while not the end of the list
printf("%d -> ", currentPtr->value);
currentPtr = currentPtr ->next;
}
}
int main(){
STUDENTIDPtr newPtr1; //creating a pointer to create a new node
STUDENTIDPtr newPtr2; //creating a pointer to create a new node
STUDENTIDPtr newPtr3; //creating a pointer to create a new node
STUDENTIDPtr newPtr4; //creating a pointer to create a new node
STUDENTIDPtr newPtr5; //creating a pointer to create a new node
//creation of the first node
newPtr1 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr2 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr3 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr4 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr5 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr1 -> value = 4; // assign data in first node
newPtr1 -> next = newPtr2;
newPtr2 -> value = 4; // assign data in first node
newPtr2 -> next = newPtr3;
newPtr3 -> value = 5; // assign data in first node
newPtr3 -> next = newPtr4;
newPtr4 -> value = 2; // assign data in first node
newPtr4 -> next = newPtr5;
newPtr5 -> value = 1; // assign data in first node
newPtr5 -> next = NULL;
currentPtr = newPtr1;
printList(newPtr1);
return 0;
}
#包括
#包括
/*自指结构*/
结构学生ID{
int value;//是整数的数据成员
struct studentID*next;//是指向下一个节点的指针的数据成员
};
typedef struct studentID studentID//将struct studentID的昵称创建为studentID
typedef STUDENTID*STUDENTIDPtr//将STUDENTID的昵称创建为STUDENTIDPtr
//全局变量
学生先前的PTR//指向列表中上一个节点的指针
学生英语//指向列表中当前节点的指针
无效打印列表(STUDENTIDPtr currentPtr){
while(currentpr!=NULL){//而不是列表的末尾
printf(“%d->”,currentPtr->value);
currentPtr=currentPtr->next;
}
}
int main(){
STUDENTIDPtr newPtr1;//创建指针以创建新节点
STUDENTIDPtr newPtr2;//创建指针以创建新节点
STUDENTIDPtr newPtr3;//创建指针以创建新节点
STUDENTIDPtr newPtr4;//创建指针以创建新节点
STUDENTIDPtr newPtr5;//创建指针以创建新节点
//创建第一个节点
newPtr1=malloc(sizeof(STUDENTID));//这是创建节点的时间
newPtr2=malloc(sizeof(STUDENTID));//这是创建节点的时间
newPtr3=malloc(sizeof(STUDENTID));//这是创建节点的时间
newPtr4=malloc(sizeof(STUDENTID));//这是创建节点的时间
newPtr5=malloc(sizeof(STUDENTID));//这是创建节点的时间
newPtr1->value=4;//在第一个节点中分配数据
newPtr1->next=newPtr2;
newPtr2->value=4;//在第一个节点中分配数据
newPtr2->next=newPtr3;
newPtr3->value=5;//在第一个节点中分配数据
newPtr3->next=newPtr4;
newPtr4->value=2;//在第一个节点中分配数据
newPtr4->next=newPtr5;
newPtr5->value=1;//在第一个节点中分配数据
newPtr5->next=NULL;
currentPtr=newPtr1;
打印列表(newPtr1);
返回0;
}
使用if-else和run-through每个链表是容易的还是有更好的方法?有两种方法会马上浮现在脑海中,使用哪种方法取决于您的具体情况,以及您是否希望保留元素的原始顺序
第一种方法: 使用双循环,一次拾取一个节点。然后迭代该节点之后的列表,如果发现重复的,则删除。重复拾取节点,直到遍历整个列表
For every node of the list
For every next_node after node
If next_node.value == node.value
Remove that next_node
这种方法保留了元素的原始顺序
我认为这种方法是你已经想到的。我建议你从这个开始
例如:
1->2->3->4->1
我将从第一个节点(1)开始,检查第二个节点、第三个节点、第四个节点,到目前为止没有发现任何重复的节点。我现在检查第五个节点,它也有值1(发现重复!),所以我将其删除
现在列表如下所示:
1->2->3->4
现在我正在寻找第二个节点的副本(我在上一次遍历中检查了第一个节点)。我查了3,我查了4,没有发现重复的。名单保持不变
现在我正在寻找第三个节点的副本。我查了4个,没有发现重复的。名单保持不变
现在我正在寻找第四个节点的副本。下一个节点为NULL,这意味着第四个节点是最后一个节点(因为我们在第一次遍历中删除了第五个节点,作为1的副本)。没有什么可检查的,列表保持不变:
1->2->3->4
观察对于我要检查是否存在重复项的每个节点,我如何遍历列表直到其结束。因此,对于每个节点,我都在进行O(N)遍历,其中N是列表的大小
我有多少个节点?N
所以这种方法的时间复杂度是N*O(N)=O(N2)
我强烈建议你自己尝试一下,然后练习。完成后,您可以阅读以检查解决方案
第二种方法: 对列表进行排序,现在列表将把重复的值分组在一起。因此,如果存在当前节点的副本,它将是其下一个节点。如果是重复节点,请删除下一个节点 现在,同样,如果当前节点有一个副本,它将是它的下一个节点。因此,执行上述操作,直到下一个节点不是当前节点的副本 然后,使下一个节点成为当前节点,并执行相同的过程
Sort list
current_node = head_node
While current_node != NULL
If current_node.value == current_node.next.value
Remove current_node.next
Else
current_node = current_node.next
这种方法不保留元素的原始顺序
同样的例子:
1->2->3->4->1
对列表进行排序:
1->1->2->3->4
我从1开始。我检查它的下一个节点,它也是1,一个重复的发现!删除下一个节点。现在名单是:
1->2->3->4
当前节点仍然是1。我检查它的下一个节点,它是2。不是复制品。名单保持不变。将下一个节点设置为当前节点
当前节点为2。检查下一个节点,它是3,不是重复的。名单保持不变。将下一个节点设置为当前节点
当前节点为3。检查下一个节点,它是4,不是重复的。名单保持不变。将下一个节点设置为当前节点
当前节点为4。它没有下一个节点,无需检查,我已完成。名单不变:
1->2->3->4
请注意,对于每个节点,我只检查其紧邻的下一个节点。然后,我继续检查最后一个节点。这就是O(N)
但是,我必须对列表进行排序,以确保重复的列表是正确的
//Global variables
STUDENTIDPtr previousPtr; //pointer to previous node in list
STUDENTIDPtr currentPtr; //pointer to current node in list
typedef STUDENTID *STUDENTIDPtr;
#include <stdio.h>
#include <stdlib.h>
/* self-referential structure*/
struct studentID{
int value; //a data member which is an integer
struct studentID *next; //a data member which is a pointer to next node
};
typedef struct studentID STUDENTID; //creating a nickname for struct studentID as STUDENTID
typedef STUDENTID *STUDENTIDPtr;
size_t remove_duplicates( STUDENTIDPtr *head )
{
size_t n = 0;
for ( ; *head != NULL; head = &( *head )->next )
{
for ( STUDENTIDPtr *next = &( *head )->next; *next != NULL; )
{
if ( ( *head )->value == ( *next )->value )
{
STUDENTIDPtr tmp = *next;
*next = ( *next )->next;
free( tmp );
++n;
}
else
{
next = &( *next )->next;
}
}
}
return n;
}
void printList(STUDENTIDPtr currentPtr){
for ( ; currentPtr != NULL; currentPtr = currentPtr ->next )
{
printf("%d -> ", currentPtr->value);
}
puts( "NULL" );
}
int main(void)
{
STUDENTIDPtr newPtr1; //creating a pointer to create a new node
STUDENTIDPtr newPtr2; //creating a pointer to create a new node
STUDENTIDPtr newPtr3; //creating a pointer to create a new node
STUDENTIDPtr newPtr4; //creating a pointer to create a new node
STUDENTIDPtr newPtr5; //creating a pointer to create a new node
//creation of the first node
newPtr1 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr2 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr3 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr4 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr5 = malloc(sizeof(STUDENTID)); //This is when a node is created
newPtr1 -> value = 4; // assign data in first node
newPtr1 -> next = newPtr2;
newPtr2 -> value = 4; // assign data in first node
newPtr2 -> next = newPtr3;
newPtr3 -> value = 5; // assign data in first node
newPtr3 -> next = newPtr4;
newPtr4 -> value = 2; // assign data in first node
newPtr4 -> next = newPtr5;
newPtr5 -> value = 1; // assign data in first node
newPtr5 -> next = NULL;
printList( newPtr1 );
size_t n = remove_duplicates( &newPtr1 );
printf( "There are removed %zu elements\n", n );
printList( newPtr1 );
return 0;
}
4 -> 4 -> 5 -> 2 -> 1 -> NULL
There are removed 1 elements
4 -> 5 -> 2 -> 1 -> NULL