• c++ 链表删除重复的数据


    //List.h

    #include <iostream>
    typedef int dataType;
    
    struct Node{
        Node():data(0),pNextNode(NULL){} //结点构造函数
        dataType data;
        Node* pNextNode;
    };
    class List{
    private:
        Node *head; //作为链表唯一的头指针
        int size;   //链表长度
    public:
        List(){head=new Node;size=0;}
        bool isEmpty();                //判断是否空表
        bool InsertList(int i,dataType elem);  //i的指标从1开始,而不是从0开始
        void PushList(dataType elem);          //在链表尾部添加元素
        bool DeleteList(int i);        //删除指定位置的元素
        void ClearList();            //清除整条链表
        void DeleteRepetitiveData();//删除重复元素
        void PrintList();            //按顺序输出链表
        int GetSize();    
        Node* Fine(int i);            //找到第i个结点并返回该结点的指针
        Node* FinePre(int i);        //找到第i个结点前的结点,返回指针
    };

    //List.cpp

    #include "List.h"
    #include <iostream>
    #include <vector>
    using namespace std;
    //判断空表
    bool List::isEmpty(){
        if(head==NULL)
            return false;
        else
            return true;
    }
    //在第i位插入数据
    bool List::InsertList(int i,dataType elem){
        if (i<1)
            return false;
        else if(head==NULL||i==1)//如果是空表
        {
            head->data=elem;
            size++;
            return true;
        }
        else if (i>size)        //位标大于链表长度时,在尾部添加
        {
            PushList(elem);
            return true;
        }
        else
        {
            Node *pre=Fine(i-1);
            Node *follow=Fine(i);
            Node *s=new Node;        //为新结点申请内存
            pre->pNextNode=s;        //连接前结点
            s->pNextNode=follow;    //连接后结点
            s->data=elem;
            size++;
            return true;
        }
    }
    //在尾部添加元素
    void List::PushList(dataType elem){
        if(head==NULL)
        {
            head=new Node;
            head->data=elem;
            size++;
        }
        else
        {
            Node *cur=head;
            while(cur->pNextNode)
                cur=cur->pNextNode;
            Node *s=new Node;
            cur->pNextNode=s;
            s->data=elem;
            size++;
        }
    }
    //打印链表
    void List::PrintList(){
        Node *cur=head;
        while (cur!=NULL)
        {
            cout<<cur->data<<"  ";
            cur=cur->pNextNode;
        }
        cout<<endl;
    }
    //size
    int List::GetSize(){
        return size;
    }
    //找到第i个结点
    Node* List::Fine(int i){
        if(i==1)
            return head;
        else
        {
            Node *cur=head;
            for (int pos=1;pos<i;pos++)
                cur=cur->pNextNode;
            return cur;
        }    
    }
    //找到i的前一个个结点
    Node* List::FinePre(int i){
        if(i<2)
        {
            cout<<"参数必须大于等于2!"<<endl;
            return NULL;
        }
        else if(i==2)
            return head;
        else
            return Fine(i-1);
    }
    //删除第i个元素
    bool List::DeleteList(int i){
        if (i<1||i>size)        //限制i的范围
            return false;
        else if(i==1)
        {
            Node *temp=head;
            head=head->pNextNode;
            delete temp;
            size--;
            return true;
        }
        else
        {
            Node *cur=this->Fine(i);
            Node *pre=this->FinePre(i);
            pre->pNextNode=cur->pNextNode; //重新连接结点
            delete cur;
            size--;
            return true;
        }
    }
    //清空整个链表
    void List::ClearList(){
        Node *temp=head;
        while (head!=NULL)
        {
            temp=head;
            head=head->pNextNode;
            delete temp;
        }
        size=0;
    }
    //删除重复元素
    void List::DeleteRepetitiveData(){
        int flag=0;        //代码运行标志,0为未运行
        if(size==1)        //只有一个元素时跳出
            return;
        Node *stand=head;//内循环结束后或者找到相同数据后才会指向下个结点
        Node *cursor;    //游标
        vector<int>storge;
        for (int i=0;i<size;i++)
        {            //用for循环是因为要得到被删除元素的位置
                    //采用握手式比较,算法的时间复杂度为O(n^2)
            cursor=stand->pNextNode;
            flag=0;
            while(cursor!=NULL)
            {
                if(stand->data==cursor->data)
                {
                    stand=stand->pNextNode;
                    flag=1;
                    //将重复的数据的下标降序保存起来
                    storge.insert(storge.begin(),i+1);
                    break;
                }
                else
                    cursor=cursor->pNextNode;
            }    
            if(!flag)
                stand=stand->pNextNode;
        }
        int itemp=storge.size();
        while (itemp--)        
        {
            this->DeleteList(storge.at(0));//提取下标,释放多余结点
            storge.erase(storge.begin());
        }
        storge.clear();    //释放vector内存
    }

    //main.cpp

    #include "List.h"
    #include <iostream>
    using namespace std;
    
    void main(){
        //List类测试代码
        List list;
        list.InsertList(1,1);
        list.InsertList(5,3);
        list.InsertList(2,2);
        list.InsertList(4,4);    
        list.PrintList();        //打印这4个元素
        cout<<"链表的长度为:"<<list.GetSize()<<endl;
        cout<<"现在删除第2个元素"<<endl;
        list.DeleteList(2);        
        list.PrintList();        
        cout<<"现在清空链表"<<endl;
        list.ClearList();        //清空链表
        cout<<"输出空表:"<<endl;
        list.PrintList();        
        
        list.PushList(4);
        list.PushList(1);
        list.PushList(7);
        list.PushList(1);
        list.PushList(1);
        list.PushList(2);
        list.PushList(2);        //压入4 1 7 1 1 2 2
        cout<<"输出链表新加入的元素:"<<endl;    
        list.PrintList();
        cout<<"删除相同元素后的链表为:"<<endl;    
        list.DeleteRepetitiveData();
        list.PrintList();
    }
    
    /*
    总结:
    1.链表类应该先写Fine()和FindPre(),再写插入和删除
    2.链表的结构应该给每一个结点加上一个下标。因为下标在
      操作时再加上的话,元素跟下标是不统一的,
      如果有元素被删除,下标将要重新分配。
     这就导致
    void List::DeleteRepetitiveData()不能用
     相对直接的方法在检测到重复数据时就删除数据,而要借助vector
    间接删除
    */
  • 相关阅读:
    单例设计模式
    Tomcat启动报错:严重: Unable to process Jar entry [moduleinfo.class]
    Liun常用命令
    Docker从入门到精通——内核兼容性
    Docker从入门到精通——配置Docker守护进程
    Docker从入门到精通——Dockerfile reference
    Docker从入门到精通——IP转发问题
    Docker从入门到精通——以非 root 用户身份管理 Docker
    Docker从入门到精通——Docker 本地镜像的漏洞扫描
    Docker从入门到精通——编写 Dockerfile 的最佳实践
  • 原文地址:https://www.cnblogs.com/zoffy/p/4009717.html
Copyright © 2020-2023  润新知