带头结点的单链表操作说明

一、单链表简介

相对于以数组为代表的“顺序表”而言,单链表虽然存储密度比较低(因为数据域才是我们真正需要的,指针域只是用来索引,我们并不真正需要它),但是却具有灵活分配存储空间、方便数据元素的删除、方便元素插入等优点

单链表是线性表链式存储的一种,其储存不连续。单链表的数据结构中包含两个变量:数据和指向下一结点的指针。一个结点只知道下一个结点的地址。一个单链表必须有一个头指针,指向单链表中的第一个结点。否则链表会在内存中丢失。

一般的链表可以不带头结点,头指针直接指向第一个节点,如下图:

但是这样的链表有一个很大的问题,就是元素插入与删除操作时,需要考虑是否要改动头指针,而改动指针如果反应在函数中,那么形参必须使用二重指针,既加大了编写程序的难度,而且还降低了可读性,容易出错,因此“带头结点的单链表”使用更方便,也就是头指针指向的节点不存放数据,只作为链表的开始,这样一来,针对第一个节点的操作和针对其他节点的操作就完全一样的,十分方便,如图所示:

 

二、带头结点的单链表各种操作

下面我们讨论一下带头结点的单链表的各种操作

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 }

 

 

posted @ 2017-06-10 12:19  皇家大鹏鹏  阅读(2358)  评论(0编辑  收藏  举报