所实现的循环单链表的结构例如以下图所看到的:

循环单链表的实现,和上一篇文章单链表的实现大致同样点击打开链接,略有差别:

1:循环推断的条件不再是s == NULL或者s->next == NULL,而是他们是否等于头指针。2: 断开链表时的处理,尾节点的next不是NULL,而是指向头结点

详细细节參考上一篇文章

头文件:SCList.h

#ifndef SCLIST_H
#define SCLIST_H#include<iostream>
#include<cassert>
using namespace std;typedef enum{ FALSE, TRUE }Status;template<class Type>
class List;template<class Type>
class ListNode
{friend class List<Type>;
private:Type data;ListNode *next;
public:ListNode() :data(Type()), next(NULL){}ListNode(Type d, ListNode<Type> *n = NULL) :data(d), next(n){}void SetData(Type d){ data = d; }Type GetData()const{ return data; }~ListNode(){}
};template<class Type>
class List
{
private:ListNode<Type> *first;ListNode<Type> *last;size_t         size;
public:List(){ListNode<Type> *s = new ListNode<Type>;assert(s != NULL);first = last = s;last->next = first;}~List(){destory();}Status push_back(const Type &x){ListNode<Type> *s = new ListNode<Type>(x);if (s == NULL)return FALSE;last->next = s;last = s;last->next = first;size++;return TRUE;}void show_list(){ListNode<Type> *s = first->next;while (s != first){cout << s->data << "->";s = s->next;}cout << "Nul." << endl;}Status push_front(const Type &x){ListNode<Type> *s = new ListNode<Type>(x);if (s == NULL)return FALSE;s->next = first->next;first->next = s;if (size == 0){last = s;last->next = first;//---------------->能够省略,think}size++;return TRUE;}Status pop_back(){if (size == 0)//{cout << "循环单链表已空,无法尾删" << endl;return FALSE;}ListNode<Type> *s = first;while (s->next != last)s = s->next;delete last;last = s;last->next = first;size--;return TRUE;}Status pop_front(){if (size == 0)//{cout << "循环单链表已空。无法头删" << endl;return FALSE;}ListNode<Type> *s = first->next;first->next = s->next;delete s;if (size == 1){last = first;last->next = first;//能够省略-------------->}size--;return TRUE;}Status insert_val(const Type &x){ListNode<Type> *s = first;while (s->next != first && s->next->data < x)s = s->next;if (s->next == first)push_back(x);else{ListNode<Type> *p = new ListNode<Type>(x);assert(p != NULL);p->next = s->next;s->next = p;size++;}return TRUE;}ListNode<Type>* find(const Type &x){if (size == 0)return NULL;ListNode<Type> *s = first->next;while (s != first){if (s->data == x)return s;s = s->next;}return NULL;}Status delete_val(const Type &x){ListNode<Type> *s = find(x);if (s == NULL){cout << "该元素不存在,无法删除" << endl;return FALSE;}if (s == last){pop_back();}else{ListNode<Type> *p = s->next;s->data = p->data;s->next = p->next;if (p == last)//------------------->>注意{last = s;}delete p;size--;}return TRUE;}//从第一个节点处断开,一分为二,头结点和第一个节点成为一个单独的循环单链表//将剩余的节点依次按值插入该链表void sort(){if (size == 0 || size == 1)return;ListNode<Type> *s = first->next;ListNode<Type> *p = s->next;last = s;  last->next = first;while (p != first){s = p;p = p->next;//insert_val(s->data);//delete s;ListNode<Type> *q = first;while (q->next != NULL && q->next->data < s->data){q = q->next;}if (q->next == NULL){last->next = s;last = s;last->next = first;}else{s->next = q->next;q->next = s;}}}//从第一个节点处断开,一分为二,头结点和第一个节点成为一个单独的循环单链表//将剩余的节点依次进行头插void reserve(){if (size == 0 || size == 1)return;ListNode<Type> *s = first->next;ListNode<Type> *p = s->next;last = s;last->next = first;while (p != first){s = p;p = p->next;s->next = first->next;first->next = s;}}size_t lenth(){return size;}void clear(){if (size == 0)return;ListNode<Type> *s = first->next;while (s != first){if (size == 1){last = first;last->next = first;}else{first->next = s->next;}delete s;size--;s = first->next;}}ListNode<Type>* next(ListNode<Type> *s){if (s == last)//最后一个节点没有后继return NULL;elsereturn s->next;}ListNode<Type>* prio(ListNode<Type> *s){if (s == first->next)//第一个节点没有前驱return NULL;ListNode<Type> *p = first;while (p->next != s){p = p->next;}return p;}void destory(){clear();delete first;first = last = NULL;}
};
#endif

測试文件:main.cpp

#include"SCList.h"int main()
{List<int> mylist;int item;int n;int select = 1;//ListNode<int> *p;while (select){cout << "*************************************** *" << endl;cout << "*[1] push_back           [2] push_front *" << endl;cout << "*[3] show_list           [4] pop_back   *" << endl;cout << "*[5] pop_front           [6] insert_val *" << endl;cout << "*[7] lenth               [8] find       *" << endl;cout << "*[9] merge               [10] delete_val*" << endl;cout << "*[11] sort               [12] reserve   *" << endl;cout << "*[13] next               [14] clear     *" << endl;cout << "*[15] prio               [0] quit_system*" << endl;cout << "请选择:>";cin >> select;switch (select){case 1:cout << "请输入要插入的元素(-1结束):>";while (cin >> item, item != -1){mylist.push_back(item);}break;case 2:cout << "请输入要插入的元素(-1结束):>";while (cin >> item, item != -1){mylist.push_front(item);}break;case 3:mylist.show_list();break;case 4:mylist.pop_back();break;case 5:mylist.pop_front();break;case 6:cout << "请输入要插入的元素:";cin >> item;mylist.insert_val(item);break;case 7:cout << "长度为:" << mylist.lenth() << endl;break;case 8:cout << "请输入要查找的元素:";cin >> item;if (mylist.find(item))cout << "it's found" << endl;elsecout << "it's not exist" << endl;break;case 9:cout << "请输入要删除的位置:";cin >> n;//mylist.delete_pos(n,item);break;case 10:cout << "请输入要删除的元素:";cin >> item;mylist.delete_val(item);break;case 11:mylist.sort();break;case 12:mylist.reserve();break;case 13:cout << "请输入要查找后继的元素:";cin >> item;//p = mylist.next(item);//if (p != NULL)//  cout << p->GetData() << endl;break;case 14:mylist.clear();break;default:break;}}system("pause");return 0;
}

转载于:https://www.cnblogs.com/lytwajue/p/7098665.html

【c++版数据结构】之循环单链表的实现(带头结点以及尾节点)相关推荐

  1. 【数据结构】循环单链表的实现(C语言)

    循环单链表应掌握以下基本操作: 1.建立一个空的循环单链表. 2.获得循环单链表的最后一个结点的位置. 3.输出循环单链表中各结点的值. 4.在循环单链表中查找值为x的结点. 5.在循环单链表中第i个 ...

  2. 带头结点单链表 和 不带头结点单链表的区别

    文章目录 不带头结点的操作 代码① 代码② 代码③ 代码④ 带头结点的操作 代码⑤ 下面的代码中,传递链表时,传的是头指针.如果是带头结点的链表,传递链表时,可以传头结点,具体可以看看 C语言实现-线 ...

  3. 带头结点单链表、不带头结点单链表(头指针单链表)

    1.头结点和头指针的区别 1.1区别: 头指针表明了链表的结点,可以唯一确定一个单链表. 头指针指向链表的第一个结点,其记录第一个存储数据的结点的地址. 头结点是点链表的第一个结点,若单链表有头结点, ...

  4. 数据结构c/c++ 头插法尾插法建立带头结点的单链表,以数组创建带头结点的单链表和不带头结点的单链表,输出打印单链表

    // // Created by 焦娇 on 2021/9/17. //#ifndef CHAPTER2_LINELINK_LLK_H #define CHAPTER2_LINELINK_LLK_H# ...

  5. c语言给定一个单链表输入k,C语言实现单链表(不带头结点)的基本操作

    链表在数据结构和算法中的重要性不言而喻.这里我们要用C来实现链表(单链表)中的基本操作.对于链表的基本概念请参考<数据结构与算法之链表>这篇博客.示例代码上传至 https://githu ...

  6. 单链表(不带头结点)

    不带头结点的节点因为插入删除的时候会改变或者删除第一个节点,所以要引入二级指针进行一系列的操作 头文件 #pragma once //不带头结点的单链表 typedef struct Node {in ...

  7. java带头结点的单链表_java编写带头结点的单链表

    /*** @ProjectName: JavaPractice * @Package: com.itwang.swordtooffer * @ClassName: LNodeOperation * @ ...

  8. 链表面试题1:反转单链表,不带头结点。

    三个指针p1,p2,p3,p1指向头结点的前一个结点,也就时指空,p2指向头结点,p3指向头结点下一个结点. p3指向p2的下一个,让p2指针域指向p1,让p1挪到p2上,再让p2指向p3.

  9. 线性表文档之循环单链表

    循环单链表 定义 概念 循环单链表是在单链表的基础上,将链表最后一个结点的 next 指针域指向了链表的第一个结点(如果单链表是带头结点的则最后一个结点的 next 指针域指向头结点:如果单链表是不带 ...

  10. 循环链表(循环单链表和双链表)

    循环链表 前言 一.循环单链表的初始化 二.判断是否为空或表尾结点 三.循环双链表的初始化 四.循环双链表的插入与删除 前言 对于循环单链表而言,在进行插入和删除时,可以让指针指向尾部,对于表头(通过 ...

最新文章

  1. 黑盒测试方法之边界值分析法
  2. sqlplus set;命令
  3. 《研磨设计模式》chap25 访问者模式Visitor(3)联合组合模式+总结
  4. 从0搭建一个Springboot+vue前后端分离项目(一)安装工具,创建项目
  5. boost::uuids::random_generator相关的测试程序
  6. Trie(字典树) : 如何实现搜索引擎的关键词提示功能?
  7. 【解题报告】Leecode911. 在线选举——Leecode每日一题系列
  8. [转]asp.net(c#)生成验证码 点击可刷新
  9. bzoj3160(FFT+回文自动机)
  10. 浙江省计算机二级excel函数,浙江省计算机二级excel练习5操作要求
  11. 一步一步学ROP之linux_x64篇
  12. Aop 是面向切面编程,
  13. Diango+Vue+mysql开发数据看板视图
  14. 成品系统搭建 一周就可以上线运营
  15. 如何用excel做多元回归分析
  16. PCM开发板模块实验指导--有刷直流马达正反转实验
  17. iOS 图片合成(一)
  18. 我的Python学习之路(一)_Mr_Ouyang
  19. 微软版我的世界服务器推荐,平台化的网易《我的世界》中国版,可能是新玩家目前的最佳选择...
  20. 双线双IP(多线多IP)域名智能解析教程

热门文章

  1. 深入理解Python的With-as语句
  2. 如何用MathType插入公式编号
  3. 读写分离数据库之MyCat
  4. linux系统共享盘,linux与其他操作系统文件共享方法
  5. 1.6.2java工业星系_我的世界1.6.4
  6. zblog php标签,201502200101 zblogphp调整“显示常用标签”个数方法
  7. 003_Jsp动作标签
  8. linux过滤脚本中的字段,Shell脚本中常用的文本过滤命令
  9. RxJava 教程第一部分:入门之 生命周期管理
  10. matlab中 三种方法计算 Ax b,在MATLAB中,方程Ax=B的解可以用哪个命令求得? matlab 求助 解方程组...