zoukankan      html  css  js  c++  java
  • 带头结点的单链表操作说明

    一、单链表简介

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

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

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

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

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

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

    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 }
  • 相关阅读:
    appium自动化测试搭建
    How to install Qt Creator on Ubuntu 18.04
    Luci
    OpenWrt 根文件系统启动过程分析
    shell 杂烩
    OpenWrt Luci 调试日志输出的一种方法
    jQuery实现购物车计算价格的方法
    js实现购物车添加,减少数量
    golang-键盘录入数据
    JAVA存储机制(栈、堆、方法区详解)
  • 原文地址:https://www.cnblogs.com/dapeng-bupt/p/6978354.html
Copyright © 2011-2022 走看看