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
間接刪除
*/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM