zoukankan      html  css  js  c++  java
  • 数据结构第五篇——线性表的链式存储之循环链表

    ♥注:未经博主同意,不得转载。

      链表是另一种形式的链式存储结构,它是线性链表的一种变形。在线性链表中,每个结点的指针都指向它的下一个结点,最后一个结点的指针域为空,表示链表的结束。若使最后一个结点的指针指向头结点,则链表呈环状,这样的链表称为循环链表

    循环链表当然也分为单链表双向列表

    通常情况下,在循环链表中设立尾指针而不设头指针,可使某些操作简化。

    循环链表的定义和操作与单链表类似,只是循环结束条件有所不同,下面只给出单循环链表的定义和部分操作,至于双向循环链表可能会在以后的项目中出现,到时再进一步探讨。

    单循环链表定义如下:

     1 typedef int Data;
     2 
     3 struct Node
     4 {
     5     Data data;            //数据 
     6     Node* next;        //指向后继的指针 
     7 };
     8 
     9 class CList
    10 {
    11     Node* head;                //创建头结点
    12     public:
    13     CList()                    //构造函数
    14     {
    15         head = new Node;
    16         head->next = head;        //头尾相接 
    17     }
    18     ~CList();                        //析构函数
    19     
    20     Data GetElem(int i);                //取第i个元素的值
    21     bool IsEmpty();                        //判断是否为空链表
    22     void Create(Data* a , int n);        //创建长度为n的循环单链表(头插法)
    23     void Create1(Data* a , int n);        //创建长度为n的循环单链表(尾插法)
    24     Node* Locate(Data e,int* i);        //查找值为e的结点,返回指向e的指针
    25     void Insert(Data x,int i);            //将数据元素x插入到第i个位置
    26     Data Delete(int i);                    //删除第i个元素
    27     //int _Delete(Data e);                //删除值为e的第一个元素
    28     int Size();                            //返回链表的长度
    29     void Clear();                        //清空
    30     void Print();                        //显示元素
    31 };

    函数功能实现如下:

      1 //计算链表长度
      2 int CList::Size()
      3 {
      4     Node* p;            //创建指针p
      5     int k;
      6     p=head->next;        //p指向第一个元素结点 
      7     k=0;
      8     while(p!=head)
      9     {
     10         p=p->next;
     11         ++k;
     12     }
     13     return k;
     14 }
     15 
     16 //显示所有元素
     17 void CList::Print()
     18 {
     19     Node* p;                //创建指针p
     20     p=head->next;            //p指向第一个元素结点 
     21     while(p!=head)    
     22     {
     23         cout<<p->data<<" ";
     24         p=p->next;
     25     }
     26     cout<<endl;
     27 }
     28 
     29 //取元素
     30 Data CList::GetElem(int i)
     31 {
     32     if(head->next == NULL)            //为空链表
     33     {
     34         cout<<"此链表为空"<<endl;
     35         exit(0);
     36     }
     37     else
     38     {
     39         Node* p;            //创建指针p
     40         int k;
     41         p=head;                //p指向头结点
     42         k=0;
     43         while(p&&k<i)        //p移到i的位置
     44         {
     45             p=p->next;
     46             k++;
     47         }
     48         return (p->data);
     49     }
     50 }    //此算法的时间复杂度为O(n)
     51 
     52 //插入操作
     53 void CList::Insert(Data x,int i)
     54 {
     55     Node* p=head;
     56     int k=0;
     57     while(p&&k<i-1)            //    将p指到第i个位置
     58     {
     59         p=p->next;
     60         ++k;
     61         
     62         if(p==head)
     63         p=p->next;
     64     }
     65     Node* s = new Node;            //创建此结点
     66     if(!s)
     67     {
     68         cout<<"空间分配失败"<<endl;
     69         exit(0);
     70     }
     71     
     72     s->data=x;                    //将元素存入创建的结点
     73     s->next=p->next;
     74     p->next=s;
     75 }
     76 
     77 //删除操作
     78 Data CList::Delete(int i)
     79 {
     80     Node* p = head;
     81     int k=0;
     82     while(p&&k<i-1)                //将p指到要删除的位置
     83     {
     84         p=p->next;
     85         ++k;
     86         
     87         if(p==head)
     88         p=p->next;
     89     }
     90     Node* q = p->next;            //暂存删除结点
     91 
     92     p->next = q->next;            //将结点隔离出来
     93     Data e=q->data;                //将删除的元素储存起来
     94     delete q;                    //释放将要删除的结点
     95     return e;
     96 }
     97 
     98 //判断链表是否为空 
     99 bool CList::IsEmpty()
    100 {
    101     if(head->next==NULL)
    102     {
    103         cout<<"此链表为空"<<endl;
    104         return true;
    105     }
    106     else
    107     {
    108         cout<<"此链表非空"<<endl;
    109         return false;
    110     }
    111 }
    112 
    113 //建立单循环链表 
    114 //第一种是头插法
    115 void CList::Create(Data* a,int n)
    116 {
    117     Node* p=NULL;
    118     Node* q=NULL;
    119     for(int i=n-1;i>=0;--i)
    120     {
    121         p=new Node;                    //创建新结点
    122         p->data=a[i];                    //将元素存入结点
    123         
    124         p->next=head->next;            //将新加入结点指向头结点后面
    125         head->next=p;                //将头结点指向新加入的结点
    126     }
    127 }
    128 
    129 //第二种是尾插法
    130 void CList::Create1(Data* a,int n)
    131 {
    132     Node* p=NULL;
    133     Node* q=head;                    //创建中间结点指针
    134     for(int i=0;i<n;++i)
    135     {
    136         p=new Node;                    //创建储存元素的新结点
    137         p->data=a[i];                //将元素存入创建的结点
    138         p->next=q->next;            //插入到终端结点之后
    139         q->next=p;                    //终端结点指向新建结点
    140         q=p;                        //q指向新建结点
    141     }
    142     p->next=NULL;
    143 }
    144 
    145 //查找给定值的结点
    146 Node* CList::Locate(Data e,int *i)
    147 {
    148     *i=1;
    149     Node* p=head->next;
    150     
    151     while(p!=head)                        //p不为空
    152     {
    153         if(p->data==e)                //找到元素
    154             return p;
    155         else
    156         {
    157             p=p->next;
    158             ++(*i);
    159         }
    160     }
    161     cout<<"当前链表中无此元素"<<endl;
    162     exit(0);
    163     return NULL;
    164 }
    165 
    166 //清空单循环链表 
    167 //保留表头结点,把链表中的
    168 //其余所有结点全部释放。
    169 void CList::Clear()
    170 {
    171     Node* p=NULL;
    172     Node* q=NULL;
    173     p=head->next;
    174     while(p!=head)
    175     {
    176         q=p;
    177         p=p->next;
    178         delete q;
    179     }
    180     head->next = NULL;
    181 }
    182 
    183 //析构函数
    184 //释放链表中的所有元素。
    185 CList::~CList()
    186 {
    187     Node* p;
    188     p=head;
    189     while(p!=head)
    190     {
    191         p=p->next;
    192         delete head;
    193         head=p;
    194     }
    195 }

    测试程序则放在main函数里:

     1 int main()
     2 {
     3     int i=0;
     4     Data e;
     5     int a[8]={2,4,6,8,5,1,7,9};
     6     
     7     CList list;                    //创建链表类
     8     list.IsEmpty();                    //判断链表是否为空
     9     list.Create(a,8);                //将数据插入
    10     list.Print();                    //显示
    11     cout<<"链表长度:"<<list.Size()<<endl;
    12     
    13     cout<<"输入要插入的元素和位置:";
    14     cin>>e>>i;
    15     list.Insert(e,i);                //插入数据
    16     list.Print();
    17     cout<<"当前链表长度为"<<list.Size()<<endl<<endl;
    18         
    19     cout<<"输入要查找的元素值:";
    20     cin>>e;
    21     list.Locate(e,&i);                    //查找某元素
    22     cout<<"这是第"<<i<<"个元素"<<endl<<endl;
    23     
    24     list.IsEmpty();                    //判断链表是否为空
    25     
    26     cout<<"输入要查找的元素位置:";
    27     cin>>i;
    28     e=list.GetElem(i);                    //查找第i个位置的元素
    29     cout<<"这个元素值为:"<<e<<endl<<endl;
    30     
    31     list.IsEmpty();                    //判断链表是否为空
    32     
    33     cout<<"输入要删除的元素位置:";
    34     cin>>i;
    35     e=list.Delete(i);                    //删除第i个位置的元素
    36     cout<<"这个元素值为:"<<e<<endl;
    37     list.Print();
    38     cout<<"当前链表长度为"<<list.Size()<<endl<<endl;
    39     
    40     cout<<"输入要删除的元素位置:";
    41     cin>>i;
    42     e=list.Delete(i);                    //删除第i个位置的元素
    43     cout<<"这个元素值为:"<<e<<endl;
    44     list.Print();
    45     cout<<"当前链表长度为"<<list.Size()<<endl<<endl;
    46     
    47     list.Clear();
    48     list.IsEmpty();                    //判断链表是否为空
    49     
    50     return 0;
    51 }

    测试情况如下:

    到此,线性表的几种基本实现已经结束了,下方可查看几种线性表的具体实现:

    1.顺序存储:http://www.cnblogs.com/tenjl-exv/p/7469316.html

    2.单链表:http://www.cnblogs.com/tenjl-exv/p/7470075.html

    3.双向链表:http://www.cnblogs.com/tenjl-exv/p/7475518.html

    这里说一下循环链表的优点:

    ① 从表中任意结点出发均可访问到表中其他结点,这使得某些操作在循环链表上容易实现。

    ② 插入删除操作中不需区分尾节点还是中间结点,以使操作简化

     

  • 相关阅读:
    javaweb学习总结(四十五)——监听器(Listener)学习二
    javaweb学习总结(四十四)——监听器(Listener)学习
    javaweb学习总结(四十三)——Filter高级开发
    javaweb学习总结(四十二)——Filter(过滤器)学习
    javaweb学习总结(四十一)——Apache的DBUtils框架学习
    javaweb学习总结(四十)——编写自己的JDBC框架
    javaweb学习总结(三十九)——数据库连接池
    javaweb学习总结(三十八)——事务
    javaweb学习总结(三十七)——获得MySQL数据库自动生成的主键
    javaweb学习总结(三十六)——使用JDBC进行批处理
  • 原文地址:https://www.cnblogs.com/tenjl-exv/p/7476246.html
Copyright © 2011-2022 走看看