单链表删除重复链表

1.定义三个指针变量*p,*q,*tp先指向第一个要扫描的结点.

2.判断链表中是否存在和p一样的结点,让q指向p,判断qnext结点是否和p相同,如果相同(1)t指向这个结点.(2)qnext指向tnext.(3)销毁t所指向的结点

3.如果qnext结点不于p结点相同,则让q向后移动,既q=q->next;

4.判断完当前p结点后,让p结点后移。

#include <iostream>
#include<stdlib.h>
using namespace std;
struct node
{
    int x;
    struct node *next;
};
//顺序建表
struct node *creatListShun(int lenth)
{
    struct node *head,*t,*p;
    int i;
    head=(struct node *)malloc(sizeof(struct node));
    head->next=NULL;
    t=head;
    for(i=0; i<lenth; i++)
    {
        p=(struct node *)malloc(sizeof(struct node));
        p->x=i%7;
        p->next=NULL;
        t->next=p;
        t=p;
    }
    return head;
}
//链表删除重复
struct node *delSame(struct node *head1)
{
    struct node *t,*p,*q;
    p=head1->next;
    while(p)
    {
        q=p;
        while(q->next)
        {
            if(q->next->x==p->x)
            {
                t=q->next;
                q->next=t->next;
                free(t);
            }
            else
                q=q->next;
        }
        p=p->next;
    }
    return head1;
};
int main()
{
    struct node *head1,*t1;
    head1=creatListShun(10);//顺序建链表
    t1=head1->next;
    cout<<"顺序建链表 :";
    while(t1!=NULL)
    {
        cout<<t1->x<<" ";
        t1=t1->next;
    }
cout<<endl;

    //删除重复
    head1=delSame(head1);
    t1=head1->next;
    cout<<"链表删除重复"<<endl;
    while(t1)
    {
        cout<<t1->x<<" ";
        t1=t1->next;
    }
    return 0;
}


单链表删除重复元素有多种实现方法,以下为你详细介绍: ### 全部删除重复元素(保留所有重复元素中的一个) 可以采用增加一个哨兵节点,其 `next` 指向当前头结点,避免把头结点删除,同时增加一个辅助指针。以下是 Java 代码实现: ```java /** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode deleteDuplicates(ListNode head) { if(head == null){ return null; } ListNode preHead = new ListNode(0); preHead.next = head; ListNode l1 = preHead; while(l1.next != null && l1.next.next != null){ if(l1.next.val == l1.next.next.val){ ListNode temp = l1.next; while(temp != null && temp.next != null && temp.val == temp.next.val){ temp = temp.next; } //temp会指向重复元素的最后一个 l1.next = temp.next; }else{ l1 = l1.next; } } return preHead.next; } } ``` 这种方法的核心思路是遍历链表,当遇到相邻节点值相同时,跳过所有重复节点,直到找到不同值的节点,将当前节点的 `next` 指向该不同值节点,从而删除重复节点 [^1]。 ### 无序单链表删除重复元素 通过双重循环遍历链表,外层循环遍历每个节点,内层循环检查后续节点是否与当前节点值相同,若相同则删除该后续节点。以下是 C++ 代码实现: ```cpp #include<iostream> using namespace std; struct LNode{ int date; LNode *next; }; struct LinkList{ LNode *head; void create(int n); void traverse(); }; void LinkList::create(int n){ head=new LNode; head->next=NULL; LNode *q=head; for(int i=0;i<n;i++){ LNode *p=new LNode; cin>>p->date; p->next=NULL; q->next=p; q=p; } } void LinkList::traverse(){ LNode *p=head->next; while(p){ if(p!=head->next) cout<<" "; cout<<p->date; p=p->next; } cout<<endl; } void deletelist(LinkList La,int &n){ //删除单链表重复的元素 LNode *p=La.head->next; while(p){ LNode *q=p,*r=p->next; while(r){ if(r->date==p->date){ LNode *s=r; q->next=r->next; r=r->next; delete s; n--; } else{ q=r; r=r->next; } } p=p->next; } } int main(){ int n; LinkList a; while(cin>>n){ a.create(n); deletelist(a,n); cout<<n<<endl; a.traverse(); } } ``` 此方法的逻辑是外层循环依次选取每个节点作为基准,内层循环遍历后续节点,若发现重复节点则删除,同时更新链表长度 [^2]。 ### 不保留重复元素(全部删除) 使用两个指针,一个指针作为标杆值,另一个指针移动寻找相同值,若找到相同值则删除该节点。以下是 C++ 代码实现: ```cpp void listDelDuplicates(node *&head) { //定义变量 node* flag = head; //flag作为标杆值 node* p = head->next; //P移动寻找相同值 while( p ) { if( flag->data == p->data ) //若flag的值和p的值相同时 { node* q = p; //定义一个q去指向p,目的是为了释放内存 flag->next = p->next; //flag的next指向p的next p = p->next; //p指向下一个结点 delete q; //释放q所指的结点 } else //若两者的值不同时,flag和p都向下一个移动 { flag = p; p = p->next; } } } ``` 该方法通过比较标杆节点和移动节点的值,若相同则删除移动节点,不同则更新标杆节点和移动节点 [^4]。 ### 有序单链表删除重复元素 使用两个指针遍历链表,确保第二个 `while` 循环中的条件顺序不能颠倒,避免内存错误。以下是 C 代码实现: ```c void DeleteRepeated(LinkList L) { Node*p, *q; p = L->next; while(p) { q = p->next; while(q!=NULL && p->data == q->data) //两个条件不可颠倒! { p->next = q->next; free(q); q = p->next; } p = p->next; } } ``` 此方法利用有序链表的特性,当相邻节点值相同时,删除后续重复节点 [^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值