数据结构-线性表-单循环链表(使用尾指针)(c++)

news/2025/1/15 21:57:50/

目录

  • 单循环链表
        • 说明
        • 注意
    • (一)无参构造函数
    • (二)有参构造函数
    • (三)析构函数
    • (四)获取长度
    • (五)打印数组
    • (六)获取第i个元素的地址
    • (七)插入
    • (八)删除
    • (九)获取值为x的元素的位置
    • (十)排序
    • (十一)连接
    • (十二)整个文件
            • CircleList.h
            • UseCircleList.cpp

单循环链表

说明

单循环链表和单链表(参考单链表)大致一样,只是尾结点要指向头结点,本文是使用尾结点rear来表示,之所以使用尾指针,是因为如果使用头结点来寻找列表最后一个元素时间复杂度为O(n),如果使用尾结点来寻找列表最后一个元素时间复杂度为O(1)

注意

  1. 第一个元素地址表示:rear->next->next;最后一个元素地址:rear
  2. 头指针的表示,单链表使用front来标识头指针,单循环链表使用rear->next来表示
  3. 单链表使用p->next=NULL判断是否为尾结点,单循环链表使用p==rear判断是否为尾结点

(一)无参构造函数

建立尾结点,使尾结点指针域指向自己,说明链表为空

template<class T>
CircleList<T>::CircleList()
{rear=new Node<T>;rear->next=rear;
}

(二)有参构造函数

这里的方法相当于单链表中使用的尾插法,

  1. 为rear开辟空间
  2. 创建头指针Headr,并把rear的地址赋给Headr
  3. 使用for循环将数组依次加入到列表中
  4. 创建一个临时结点temp
  5. 为temp值域赋值,并把其地址赋给rear->next
  6. 修改rear地址
  7. 最后将rear指回头结点
template<class T>
CircleList<T>::CircleList(T a[],int len)
{rear = new Node<T>;Node<T>* Headr;Headr = rear;for (int i=0;i<len;i++){Node<T>* temp = new Node<T>;temp->data = a[i];rear->next = temp;rear = temp;}rear->next = Headr;
}

(三)析构函数

与单链表相似,只是最后rear要单独释放

template<class T>
CircleList<T>::~CircleList()
{Node<T>* p=rear->next;while(p!=rear){rear->next=p;p=p->next;delete rear->next;}delete rear;
}

(四)获取长度

与单链表相似,只是j的初始值要为1,因为while循环的终止条件为p!=rear,但是rear为最后一个元素,需要算上,所以j的初始值为1

template<class T>
int CircleList<T>::GetLength()const
{int j=1;Node<T>* p=rear->next->next;while(p!=rear){j++;p=p->next;}return j;
}

(五)打印数组

因为while循环的终止条件为p!=rear,但是rear为最后一个元素,所以需要单独打印rear;其中if(i%5==4)是控制5个元素为一行

template<class T>
void CircleList<T>::Print()const
{Node<T>* p=rear->next->next;int i=0;while(p!=rear){std::cout<<p->data<<" ";if(i%5==4)std::cout<<std::endl;p=p->next;i++;}std::cout<<rear->data<<std::endl;
}

(六)获取第i个元素的地址

与单链表相似,需要注意的是,如果取最后一个元素,需要使用if(GetLength()==i)return rear;单独判断

template<class T>
Node<T>* CircleList<T>::Get(int i)const
{int j=0;Node<T>* p=rear->next;if(GetLength()==i)return rear;while(p!=rear&&j!=i){p=p->next;j++;}return p;
}

(七)插入

和单链表略有不同

  1. 先判断插入位置是否正确
  2. 然后在插入
template<class T>
void CircleList<T>::Insert(int i,T x)
{Node<T>* p=rear->next;if(i<0||i>GetLength())throw"位置异常";if(i!=1)p=Get(i-1);Node<T>* s=new Node<T>;s->data=x;s->next=p->next;p->next=s;
}

(八)删除

  1. 获取第i-1位置的地址
  2. q表示第i个元素
  3. 摘链
  4. 释放

如果删除最后一个元素需要单独释放:

  1. 用temp存储最后元素的地址
  2. 让rear指向倒数第二个元素
  3. 摘链,让倒数第二个元素指向头结点
  4. 释放
template<class T>
void CircleList<T>::Delete(int i)
{Node<T>* p=rear->next;if(i!=1)p=Get(i-1);if(i==GetLength()){Node<T>* temp=rear;rear=p;rear->next=temp->next;delete temp;}else{Node<T>* q=p->next;p->next=q->next;delete q;}
}

(九)获取值为x的元素的位置

template<class T>
int  CircleList<T>::Location(T x)const
{int j=0;Node<T>* p=rear->next->next;if(x==rear->data)return GetLength();while(p!=rear){j++;if(p->data==x)return j;p=p->next;}
}

(十)排序

使用的是冒泡排序,循环的终止条件与单链表不同

template<class T>
void CircleList<T>::sort()
{for(int i=1;i<=CircleList<T>::GetLength();i++){Node<T>* p=rear->next->next;while(p!=rear){if(p->data>p->next->data){T t;t=p->next->data;p->next->data=p->data;p->data=t;}p=p->next;}}
}

(十一)连接

  1. 保存b链的头结点
  2. b链的尾指向当前链表的头
  3. 当前链表的尾,指向b链的第一个元素
  4. 修改尾指针
  5. 将b链置空,并且把b.rear指向这个节点
template<class T>
void CircleList<T>::Connect(CircleList<T> &b)
{if(b.rear==b.rear->next)return;Node<T>* p=b.rear->next;//保存b链的头结点b.rear->next=rear->next;//b链的尾指向当前链表的头rear->next=p->next;//当前链表的尾,指向b链的第一个元素rear=b.rear;//修改尾指针b.rear=p->next=p;//将b链置空,并且把b.rear指向这个节点
}

(十二)整个文件

CircleList.h
#ifndef CIRCLELIST_H_
#define CIRCLELIST_H_
#include<iostream>
template<class T>
struct Node
{T data;struct Node<T>* next;
};
template<class T>
class CircleList
{
private:Node<T>* rear;
public:CircleList();CircleList(T a[],int len);~CircleList();int GetLength()const;void Print()const;void Insert(int i,T x);void Delete(int i);Node<T>* Get(int i)const;int Location(T x)const;void sort();void Connect(CircleList<T> &b);
};
template<class T>
CircleList<T>::CircleList()
{rear=new Node<T>;rear->next=rear;
}
template<class T>
CircleList<T>::CircleList(T a[],int len)
{rear = new Node<T>;Node<T>* Headr;Headr = rear;for (int i=0;i<len;i++){Node<T>* temp = new Node<T>;temp->data = a[i];rear->next = temp;rear = temp;}rear->next = Headr;
}
template<class T>
CircleList<T>::~CircleList()
{Node<T>* p=rear->next;while(p!=rear){rear->next=p;p=p->next;delete rear->next;}delete rear;
}
template<class T>
int CircleList<T>::GetLength()const
{int j=1;Node<T>* p=rear->next->next;while(p!=rear){j++;p=p->next;}return j;
}
template<class T>
void CircleList<T>::Print()const
{Node<T>* p=rear->next->next;int i=0;while(p!=rear){std::cout<<p->data<<" ";if(i%5==4)std::cout<<std::endl;p=p->next;i++;}std::cout<<rear->data<<std::endl;
}
template<class T>
void CircleList<T>::Insert(int i,T x)
{Node<T>* p=rear->next;if(i<0||i>GetLength())throw"位置异常";if(i!=1)p=Get(i-1);Node<T>* s=new Node<T>;s->data=x;s->next=p->next;p->next=s;
}
template<class T>
void CircleList<T>::Delete(int i)
{Node<T>* p=rear->next;if(i!=1)p=Get(i-1);if(i==GetLength()){Node<T>* temp=rear;rear=p;rear->next=temp->next;delete temp;}else{Node<T>* q=p->next;p->next=q->next;delete q;}
}
template<class T>
Node<T>* CircleList<T>::Get(int i)const
{int j=0;Node<T>* p=rear->next;if(GetLength()==i)return rear;while(p!=rear&&j!=i){p=p->next;j++;}return p;
}
template<class T>
int  CircleList<T>::Location(T x)const
{int j=0;Node<T>* p=rear->next->next;if(x==rear->data)return GetLength();while(p!=rear){j++;if(p->data==x)return j;p=p->next;}
}
template<class T>
void CircleList<T>::sort()
{for(int i=1;i<=CircleList<T>::GetLength();i++){Node<T>* p=rear->next->next;while(p!=rear){if(p->data>p->next->data){T t;t=p->next->data;p->next->data=p->data;p->data=t;}p=p->next;}}
}
template<class T>
void CircleList<T>::Connect(CircleList<T> &b)
{if(b.rear==b.rear->next)return;Node<T>* p=b.rear->next;//保存b链的头结点b.rear->next=rear->next;//b链的尾指向当前链表的头rear->next=p->next;//当前链表的尾,指向b链的第一个元素rear=b.rear;//修改尾指针b.rear=p->next=p;//将b链置空,并且把b.rear指向这个节点
}
#endif // CIRCLELIST_H_
UseCircleList.cpp
#include<iostream>
#include"CircleList.h"
const int SIZE=10;
int main()
{using std::cout;using std::endl;int ss[SIZE]={9,3,4,1,5,0,8,6,2,7};int qq[5]={0,1,2,3,4};CircleList<int> Grade(ss,SIZE);CircleList<int> B(qq,5);cout<<"链表内容:"<<endl;Grade.Print();cout<<"长度为:"<<endl;cout<<Grade.GetLength()<<endl;cout<<"查找5的位置:"<<endl;cout<<Grade.Location(5)<<endl;cout<<"删除第10个位置后的内容:"<<endl;Grade.Delete(10);Grade.Print();cout<<"此时长度为:"<<endl;cout<<Grade.GetLength()<<endl;cout<<"在第9个位置插入11的内容:"<<endl;Grade.Insert(9,11);Grade.Print();cout<<"排序后:"<<endl;Grade.sort();Grade.Print();Grade.Connect(B);cout<<"连接后:"<<endl;Grade.Print();return 0;
}

http://www.ppmy.cn/news/872970.html

相关文章

链表(单/双/单循环/双循环)

文中链接附上java版代码 1.单链表 单链表是一种链式存储的数据结构&#xff0c;方便插入/删除数据元素&#xff0c;对比数组&#xff0c;在进行插入删除等操作时&#xff0c;更节省空间。单链表中每一个结点的构成都是由数据元素指针构成的 2.单循环链表 单循环链表与单链表…

单循环链表实现(设立尾指针)(第二章 P35)

设立尾指针的单循环链表 单链的循环链表结点的存储结构和单链表的存储结构一样&#xff0c;所不同的是&#xff1a;最后一个结点的 next 域指向头结点&#xff0c;而不是“空”。这样&#xff0c;由表尾很容易找到表头。 但若链表较长&#xff0c;则由表头找到表尾较费时&#…

快速排序的实现(单边循环、双边循环、非递归的实现)

文章目录 前言双边循环法思路梳理代码展示总结 单边循环法思路梳理代码展示 非递归的实现思路梳理代码展示 总结 前言 上一篇文章讲解了冒泡排序的优化&#xff0c;现在来总结一下快速排序。快速排序作为经典的排序算法之一&#xff0c;其实也用到了冒泡排序的思想&#xff0c…

单循环赛积分至少多少才能保证一定出线?

4支球队在同一小组进行单循环足球比赛&#xff0c;争夺出线权。比赛规则规定&#xff1a;胜一场得3分&#xff0c;平一场得1分&#xff0c;负一场不得分。小组中积分最高的两个队&#xff08;有且只有两个队&#xff09;出线。小组赛结束后&#xff0c;如果A队没有全胜&#xf…

数据结构—带头结点的单循环链表

1.基本操作 循环链表的特点是最后一个元素的指针域指向头结点。 因此对于循环链表的初始化&#xff08;设表的头结点是L&#xff0c; 不再是L->nextNULL&#xff0c;而是L->nextL。循环链表为空时&#xff0c;头结点的下一个结点依然是头结点本身。因此但虚幻链表的初始…

C语言数据结构篇——单循环链表的创建,插入,节点删除,打印等操作

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;对于计算机的学习者来说&#xff0c;初期的学习无疑是最迷茫和难以坚持的&#xff0c;中后期主要是经验和能力的提高&#xff0c;我也刚接触计算机1年&#xff0c;也在不断的探索&#xf…

用单循环链表实现约瑟夫环(c语言)

首先我是设置的链表节点的元素包括三个&#xff1a;1.每个人的各自拥有的顺序&#xff08;math表示&#xff09;2.每个人所拥有的密码&#xff08;data表示&#xff09;3.指针元素指向下一个&#xff1a; typedef struct node {int math; //math为人的顺序// int data; //da…

单循环赛贝格尔编排法实现

单循环赛&#xff0c;是指所有参赛队伍都需跟其他队伍比赛一次&#xff0c;根据比赛得分&#xff0c;胜负场次来排列名次。比赛队伍为单数时&#xff0c;轮数等于队伍数&#xff0c;为双数时&#xff0c;轮数等于队伍数减一。如5支队伍需比赛5轮&#xff0c;6支队伍需比赛5轮。…