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