1. 程式人生 > >新手上路,勿噴。C++連結串列的建立,遍歷,刪除,插入等等

新手上路,勿噴。C++連結串列的建立,遍歷,刪除,插入等等

//list.h

#pragma once template<typename T>class slistNode { public:  slistNode() { next = nullptr; cout << "呼叫了slistnode的建構函式" << endl; }  ~slistNode() {delete next;cout << "呼叫了slistnode的解構函式" << endl;};  T data;  slistNode* next; };

template<typename T> class myslist {  private:   unsigned int listlength;    slistNode<T>* headnode;   public:   myslist();//初始化     ~myslist();//用於刪除lastnode,headnode。他們動態分配了記憶體   unsigned int length();//連結串列元素的個數         bool add(int n);//在連結串列的頭部插入節點        void traversal();//遍歷整個連結串列並列印         bool isEmpty();//判斷連結串列是否為空         slistNode<T>* find(T x);//查詢第一個值為x的節點,返回節點的地址,找不到返回NULL         void Delete(T x);//刪除第一個值為x的節點         bool insert(T x,int n);//在第n個節點後插入值為x的節點          bool insertlast(T x);//在連結串列的尾部插入節點 }; template<typename T> myslist<T>::~myslist() {  delete headnode;  cout << "呼叫的myslist的解構函式" << endl; }

template<typename T> myslist<T>::myslist() {  cout << "呼叫的myslist的建構函式" << endl;  headnode = new slistNode<T>();//這裡呼叫預設建構函式,所以head->next=nullptr;如果有形參,則呼叫對應的建構函式。  headnode->data = 0;  listlength = 0; }

template<typename T> unsigned int myslist<T>::length() {  return listlength; }

template<typename T> bool myslist<T>::add(int n) {  int i = 0;  for (i; i < n; i++)  {   cout << "請輸入你想插入的第" <<n-i << "個數據";   T data1;   cin >> data1;   cout << endl;   //下面這個動態指標分配了地址的,這樣每次後生成的位置都會指向在它之前生成的那個節點的指標域。   slistNode<T>* node = new slistNode<T>();   if (node == nullptr)   {    cout << "動態記憶體分配失敗" << endl;    return 0;   }   //每次頭節點指向的位置都是上一次迴圈生成的節點的地址,這使得每個節點都是在頭節點後面插入的。   node->next = headnode->next;   node->data = data1;   headnode->next=node;  }  listlength = listlength + n;  return 1; }

template<typename T>

void myslist<T>::traversal() {  if (headnode->next == nullptr)   cout << "該連結串列的長度為0" << endl;  else  {   slistNode<T>* node = headnode;   while (node->next != nullptr)   {    cout << "連結串列中的資料為" << ": "<<node->next->data<<endl;    node = node->next;   }   cout << "\n輸出完畢" << endl;  }

}

template<typename T> bool myslist<T>::isEmpty() {  if (headnode->next == nullptr)  {   cout << "連結串列已經空了" << endl;   return true;  }  else  {   cout << "連結串列非空" << endl;   return false;  } }

template<typename T> void myslist<T>::Delete(T x) {  slistNode<T>* node= headnode;  while (node->next != nullptr)  {   if (node->next->data == x)   {    slistNode<T>* node1 = node->next;    node1 = node->next;    node->next = node1->next;    listlength = listlength - 1;   }   else       node = node->next;  }  cout << "該連結串列沒有該值" << endl; }

template<typename T> bool myslist<T>::insert(T x,int n) {  slistNode<T>* node = new slistNode<T>();  if (node == nullptr)  {   cout << "動態記憶體分配失敗" << endl;   return 0;  }  node->next = headnode->next;//注意:這裡將node=headnode是錯誤的,後者是將指標headnode賦給node,這會導致node與headnode指向同一個記憶體,  //使得原先分配給node的記憶體洩漏,同時,導致travel時,由於headnode地址和Node一樣,從而headnode->next==headnode  if (n < 0)  {   cout << "你輸入的位置不合理" << endl;   return 0;  }  else if (n == 0)  {   node->data = x;   headnode->next = node;   return 1;  }  else if (n > listlength)  {   cout << "你輸入的位置超過連結串列的長度" << endl;   return 0;  }  else if (0 < n&&n < listlength)  {   if (node->next == nullptr)   {    cout << "你輸入的位置不合理" << endl;    return 0;   }   else   {    slistNode<T>* node1 = headnode;    int i = 0;    while (i < n)    {     node1 = node1->next;//不要給指向新節點的指標重新賦值,這回改變指標的地址,從而建立新節點的意圖會失敗。使用中間指標     i++;    }    node->next = node1->next;    node1->next = node;       node->data = x;    return 1;   }  } }

template<typename T> bool myslist<T>::insertlast(T x) {  slistNode<T>* node = new slistNode<T>();  if (node == nullptr)  {   cout << "動態記憶體分配失敗" << endl;   return 0;  }  if (headnode->next == nullptr)  {   headnode->next = node;   node->data = x;  }  else  {   slistNode<T>* node1 = headnode;   while (node1->next != nullptr)   {    node1 = node1->next;   }   node1->next = node;   node->data = x;   listlength = listlength + 1;  }  }

template<typename T> slistNode<T>* myslist<T>::find(T x) {  slistNode<T>* node =headnode;  if (node->next == nullptr)  {   cout << "該連結串列沒有值:" << x<<endl;  }  else  {   int i = 0;   while (node->next != nullptr)   {    i = i + 1;    if (node->next->data == x)    {     cout << "連結串列中該值是第:" << i << "個位置" << endl;     cout << "它的地址為:" << node << endl;     return node;    }    else     node = node->next;   }   cout << "該連結串列沒有值:" << x << endl;  } }

//1,使用new動態分配記憶體的指標物件,不手動釋放記憶體時,是不會呼叫解構函式的,但如果該類的物件是包含在另一個物件裡面,則當另一個物件生命結束時, //則會先呼叫該類的物件解構函式,再呼叫另一個物件的解構函式。 //2,將一個物件指標賦值為空,還是分配了記憶體的 //3,在物件釋放之前,不要將其對應的指標賦值新指標。這會使得記憶體洩漏

//main.cpp

#include"List2.h" #include<iostream> using namespace std; int main() {  {  myslist<int> list;  list.isEmpty();  cout << "連結串列的長度為:" << list.length() << endl;  int n;  cout << "請輸入連結串列首部插入資料的個數:";  cin >> n;  cout << endl;  list.add(n);  list.traversal();  list.isEmpty();  cout << "連結串列的長度為:" << list.length() << endl;  cout << "請輸入你想要在連結串列中尋找的值:";  int n1;  cin >> n1;  cout << endl;  slistNode<int>* b=list.find(n1);  list.Delete(n1);  cout << "在刪除值:" << n1 << "後,連結串列的中的值為:";  list.traversal();  int m, n2;  cout << "請輸入你想插入連結串列中值的大小:";  cin >> m;  cout << endl;  cout << "請輸入你想插入連結串列中值的位置";  cin >> n2;  cout << endl;  list.insert(m,n2-1);  cout << "在插入新值"<<m<<"後,連結串列中的值為";  list.traversal();  int x;  cout << "請輸入你想在連結串列尾部插入值的大小:";  cin >> x;  cout << endl;  list.insertlast(x);  list.traversal();

  }  system("pause");  return 0; }

菜鳥一隻