1. 程式人生 > >帶頭結點的單鏈表操作說明

帶頭結點的單鏈表操作說明

內存 arr 位置 not space n) end front tin

一、單鏈表簡介

相對於以數組為代表的“順序表”而言,單鏈表雖然存儲密度比較低(因為數據域才是我們真正需要的,指針域只是用來索引,我們並不真正需要它),但是卻具有靈活分配存儲空間、方便數據元素的刪除、方便元素插入等優點

單鏈表是線性表鏈式存儲的一種,其儲存不連續。單鏈表的數據結構中包含兩個變量:數據和指向下一結點的指針。一個結點只知道下一個結點的地址。一個單鏈表必須有一個頭指針,指向單鏈表中的第一個結點。否則鏈表會在內存中丟失。

一般的鏈表可以不帶頭結點,頭指針直接指向第一個節點,如下圖:

技術分享

但是這樣的鏈表有一個很大的問題,就是元素插入與刪除操作時,需要考慮是否要改動頭指針,而改動指針如果反應在函數中,那麽形參必須使用二重指針,既加大了編寫程序的難度,而且還降低了可讀性,容易出錯,因此“帶頭結點的單鏈表”使用更方便,也就是頭指針指向的節點不存放數據,只作為鏈表的開始,這樣一來,針對第一個節點的操作和針對其他節點的操作就完全一樣的,十分方便,如圖所示:

技術分享

二、帶頭結點的單鏈表各種操作

下面我們討論一下帶頭結點的單鏈表的各種操作

1、鏈表數據結構的聲明

1 using namespace std;
2 const int MAXSIZE = 1000;
3 template <class T>
4 struct Node
5 {
6     T data;          //數據域
7     Node *next;  //指針域
8 };

2、鏈表模板類的聲明

 1 template <class T>
 2 class LinkList
 3 {
 4     public:
 5         LinkList(){front = new
Node<T>;} //the constructor function without arguments 6 LinkList( T a[], int n); //the constructor function initialized by array of n elements 7 ~LinkList(); 8 int GetLength(); //get the length of the LIST 9 void PrintList(); //print the element of the list
10 void Insert(int i,T x);// insert element x in the i-th location 11 T Delete(int i); //delete the i-th element and return its value 12 Node<T> *Get(int i); //get the address of i-th element 13 int Locate(T x); //find the element whose value is x and return its index 14 private: 15 Node<T> *front; //head pointer 16 };

3、用頭插法建立新鏈表,也就是每次插入的新節點都在鏈表的頭部,註釋部分給出的是尾插法的實現方式
 1 template <class T>
 2 LinkList<T>::LinkList(T a[], int n)
 3 {
 4     // insert element at the first location of the existing link list
 5     front  = new Node<T>;
 6     front->next = NULL;
 7     for(int i=n-1; i>=0; i--)
 8     {
 9         Node<T> *s = new Node<T>;
10         s->data = a[i];
11         s->next = front->next;
12         front->next = s;
13     }
14     // insert element at the tail of the existing link list
15 
16     /*
17         front =  new Node<T>;
18     Node<T> *r = front;
19     for(int i=0; i<n; i++)
20     {
21         Node<T> *s = new Node<T>;
22         s->data = a[i];
23         r->next = s;
24         r=s;
25     }
26     r->next = NULL;
27     */
28 }

4、打印鏈表

 1 template <class T>
 2 void LinkList<T>::PrintList()
 3 {
 4     Node<T> *p = front;
 5     if(p->next==NULL)
 6       cout<<"link is enpty"<<endl;
 7     else
 8       {
 9           p = p->next;
10           while(p)
11           {
12              cout<<p->data<<" ";
13            p = p->next;    
14         }
15       }
16 }

5、插入節點

 1 template <class T>
 2 void LinkList<T>::Insert(int i,T x)
 3 {
 4      Node<T> *p = front;
 5      if(i!= 1) p=Get(i-1);  // if not insert the elelment in the first location
 6      if(p)
 7      {
 8          Node<T> *s = new Node<T>;
 9          s->data = x;
10          s->next = p->next;
11          p->next = s;
12      }
13      else 
14         cout<<"error!"<<endl;
15 }

6、刪除節點

 1 template <class T>
 2 T LinkList<T>::Delete(int i)
 3 {
 4     Node<T> *p = front;
 5     if(i!=1)  p = Get(i-1);
 6     Node<T> *q = p->next;
 7     p->next = q->next;
 8     T x = q->data;
 9     delete q;
10     return x;
11 }

7、按位查找節點,返回第i個節點的地址

 1 template <class T>
 2 Node<T> *LinkList<T>::Get(int i)
 3 {
 4     Node<T> *p = front->next;
 5     int j=1;
 6     while(p&&j!=i)
 7     {
 8         p = p->next;
 9         j++;
10     }
11     return p;
12 }

8、按值查找,返回給定值對應的節點的序號

 1 template <class T>
 2 int LinkList<T>::Locate(T x)
 3 {
 4     
 5     Node<T> *p = front->next;
 6     int j=1;
 7     while(p)
 8     {
 9         if(p->data==x) return j;
10         p = p->next;
11         j++;
12     }
13     return -1;    //search fail
14 }

9、獲取鏈表長度

 1 template <class T>
 2 int LinkList<T>::GetLength()
 3 {
 4     Node<T> *p = front->next;
 5     int count=0;
 6     while(p)
 7     {
 8         p = p->next;
 9         count++;
10     }
11     return count;    //get the length of linklist
12 }

10、析構函數

 1 template <class T>
 2 LinkList<T>::~LinkList()
 3 {
 4     Node<T> *p = front;
 5     while(p)
 6     {
 7         front = p;
 8         p = p->next;
 9     }
10 }

11、主函數(由於使用模板類實現,以上所有代碼建議放入 .h頭文件,主函數則放入.cpp文件 所有代碼在dev c++環境中測試通過)

 1 /*
 2 線性表相關成員函數的實現 
 3 */
 4 #include <iostream> 
 5 #include <cmath>
 6 #include <stdlib.h>
 7 #include "linked_list.h"
 8 using namespace std;
 9 int  main()   
10 {
11   int a[7] = {1,2,3,4,5,6,7};
12   LinkList <int> list(a,7);
13   list.PrintList();
14   cout<<endl;
15   cout<<list.Get(3)<<endl;
16   Node<int> temp = *list.Get(3);
17   cout<<temp.data<<endl;
18   //cout<<*(list.Get(3))<<endl;
19   cout<<list.GetLength()<<endl;
20   list.Insert(3,11);
21    cout<<list.GetLength()<<endl;
22   list.PrintList();
23   cout<<list.Locate(5)<<endl;
24   int x = list.Delete(4); 
25   cout<<"刪除元素:"<<x<<endl;
26   list.PrintList();
27   //int p = list.Locate(1000);
28   //cout<<"元素4的位置:"<<p<<endl; 
29   system("pause");
30   return 0;
31 }

帶頭結點的單鏈表操作說明