循环链表

C语言中单向循环链表与双向循环链表详解 每日一句 It’s gonna be ok. 一切都会好的。 内容概要 单向循环链表 首先来看看图示: 图展示的是一个单向循环链表,他跟以上的单向链表对比只是多了一个指向头结点的 指针,因此,他们的算法几乎是一样的。 第一,设计节点。 单向循环链表的节点跟单向链表完全一致。 第二,初始化空链表。 跟单向链表类似,我们既可以初始化一个带有头结点的空循环链表,也可以不要头结点: 这边把两个步骤放在一起了 linklist init_list(void) // 带有头结点的单循环链表 { linklis 阅读详情
/*
 * =====================================================================================
 *
 *       Filename:  d_list.h
 *
 *    Description:  看了循环链表,写个代码练习练习 
 *                      循环链表
 *			优点:  删除操作节点或整个链表的操作可以在常数的时间内完成
 *					
 *
 *        Version:  1.0
 *        Created:  08/25/2012 05:55:21 PM
 *       Revision:  none
 *       Compiler:  g++
 *
 *         Author:  lsff (lsff), 
 *   Organization:  
 *
 * =====================================================================================
 */


#ifndef CLIST_H
#define CLIST_H
#include <iostream>
using namespace std;


typedef int T;
struct lnode
{
	T data;
	lnode *next;
	lnode(const T& data=T()):data(data),next(NULL){}
};


typedef lnode* pNode;


class clist
{
	private :
		static pNode avail;
		static int cl_num;
		pNode head;
		size_t size;
	public:
		clist():head(NULL), size(0){ ++clist::cl_num;}
		~clist(){
			cout<<__FUNCTION__<<endl;
			if(0==--cl_num) removeFrom(avail);
			removeAll();
		}
		clist(clist& orig);
		clist& operator=(clist& rhs);


		const size_t& getSize()const { return size;}
		pNode& getNodePtr(const int& n) throw(const char*);
		void insertAt(const T& data, const int& n) throw(const char*);
//		const T& getDataAt(const int& n) const throw(const char*);
//		const T operator[](const int& n)const  throw(const char*);
		T& operator[](const int& n) throw(const char*);
	    void add(const T& data);
		void removeAt(const int&n) throw(const char*);
		void removeFrom(pNode& ptr);
		const int find(const T& data, const int&startN=0) throw(const char*);
		void removeAll();
		bool isEmpty() { return 0==size;}	
		void travel();
		friend ostream& operator<<(ostream& os, const clist& cl);
		pNode get_node(const T& data);
		// 测试函数
		void showNUM()
		{
			cout<<clist::cl_num<<endl;
		}
		void showAvail()
		{
			cout<<"avail:";
			pNode tmp=avail;
			while(tmp)
			{
				cout<<tmp->data<<" ";
				tmp=tmp->next;
			}
			cout<<endl;
		}
};


#endif 

cpp :
#include "clist.h"

pNode clist::avail=NULL;
int clist::cl_num=0;


clist::clist(clist& orig):head(NULL),size(0)
{
	++clist::cl_num;  //更新static clist::cl_num
	this->size=0;
	for(int i=0;i<orig.size;i++)
	  this->add(orig[i]);
}


clist& clist::operator=(clist& rhs)
{
	this->removeAll(); //赋值函数对旧值处理
	this->size=0;
	for(int i=0;i<rhs.size;i++)
	  this->add(rhs[i]);
}


//返回值是第n个节点的地址引用-> 就是第n-1个节点的链域的引用
//n:0~size -> 有连个指针指向头节点,head 和 第 size-1的链域
// n=0 n=size 的返回值是相同的
pNode& clist::getNodePtr(const int& n) throw(const char*)
{
	if(n<0 || n>size) throw "超出节点范围";
	if(0==n) return head;
	pNode Ptr=head;
	for(int i=1;i<=n-1;++i) Ptr=Ptr->next;
	return Ptr->next;
}


// 在第n个节点前插入,就是修改第n-1个节点的链域
// 与单链表不同的一点只有在插入到第一个元素的时候,需要更新两个指针:
//		1)head 值 2) 最后一个元素的链域
void clist::insertAt(const T& data, const int& n) throw(const char*)
{
	if(n<0 || n>size) throw "超出节点范围";// n==size --> 追加到末尾
	pNode newNode = this->get_node(data);
	if(0==n) this->getNodePtr(size)=newNode;  //更新最后节点的链域
	pNode& ptr=getNodePtr(n); 
	newNode->next = ptr;
	ptr = newNode;	
	++this->size;
}


T& clist::operator[](const int& n) throw(const char*) //非const成员访问,并可以修改返回值
{
	if(n<0 || n>=size) throw "超出节点范围";
	return 	getNodePtr(n)->data;
}


void clist::add(const T& data)
{
	this->insertAt(data, this->size);
}	


//释放节点,返回给avail(回收空间)
//回收一个节点,只要把节点查到类的静态链 avail头部就行了
void clist::removeAt(const int&n) throw(const char*)
{
	if(n<0 || n>=size) throw "超出节点范围"; 
	pNode& ptr=getNodePtr(n);
	pNode tmp=ptr;
	ptr=ptr->next;
	tmp->next=avail;
	avail=tmp;
}


// 用于释放avail的空间 <-- 已申请的节点真正的释放
// 当没有链表存在的时候,就释放类静态空间的可利用空间
void clist::removeFrom(pNode& ptr)
{
	cout<<"real delete clist!"<<endl;
	pNode tmp=ptr;
	while(ptr)
	{
		ptr=ptr->next;	
		delete[] tmp;
		tmp=ptr;
	}
	//过程中把avail置为NULL
}


const int clist::find(const T& data, const int& startN) throw(const char*)
{
	if(startN<0 ||startN>=size)  return -1;
	pNode ptr = getNodePtr(startN);
	int i=startN;
	while(ptr){
		if(data==ptr->data) return i;
		ptr=ptr->next;
		++i;
		if(ptr==head) break;
	}
	return -1;
}


//删除某条循环链表,就是把它回收到avail中
//只需注意两点:被回收的链表第一个节点的链域
//				指向avail; 而把avail值替换为
//				回收链表中第二个节点的首地址
void clist::removeAll()
{
	if(!head) return;
	pNode tmp=head->next;
	head->next=clist::avail;
	clist::avail=tmp;	
	head=NULL; //链表为空
	size=0; //error1
}


void clist::travel()
{
	pNode ptr=head;
	while(ptr)
	{
		cout<<ptr->data<<" ";
		ptr=ptr->next;
		if(ptr==head) break;
	}
	cout<<endl;
}


ostream& operator<<(ostream& os, const clist& cl)
{
	pNode ptr=cl.head;
	while(ptr)
	{
		os<<ptr->data<<" ";
		ptr=ptr->next;
		if(ptr==cl.head) break;
	}
	return os;
}


pNode clist::get_node(const T& data)
{
	if(!clist::avail) return new lnode(data);
	avail->data=data;	
	pNode rNode=avail;
	avail=avail->next;
	return rNode;
}

测试:
#include "clist.h"

int main()
{
	try{
		clist cl1;
		cl1.add(1);
		cl1.add(2);
		cl1.add(3);
		cout<<"cl1.find(1):"<<cl1.find(1)<<endl;
		cout<<"cl1.find(2):"<<cl1.find(2)<<endl;
		cout<<"cl1.find(4):"<<cl1.find(4)<<endl;
		cl1.insertAt(5,0);
		cl1.travel();
		cout<<"cl1.find(5):"<<cl1.find(5)<<endl;
		cout<<"cl1.size:"<<cl1.getSize()<<endl;
		cl1.insertAt(6,4);
		cl1.travel();
		cout<<"cl1.find(6):"<<cl1.find(6)<<endl;
		cout<<cl1[4]<<endl;

		clist cl2=cl1;
		cl2.removeAll();
		cl1.showAvail();
		cl1.travel();

		clist cl3;
		cl3=cl2;
		cl1.travel();	
		cl1.showAvail();
		cl1.removeAt(3);
		cl1.travel();	
		cl1.showAvail();
	}catch(const char* e)
	{
		cout<<e<<endl;
	}
	return 0;
}

数据结构——单向循环链表、双链表、双向循环链表 m,数到m的人出圈,然后从出圈的下一个人(m+1)开始重复此过程,直到 全部人出圈,于是得到一个出圈人员的新序列。如当n=8,m=4时,若从第一个位置数起,则所得到的新的序列 为4, 8, 5, 2, 1, 3, 7, 6。指针域:存储节点之间的关系,下一个节点的地址,单向循环链表的指针域指向该节点的地址。双向循环链表:尾节点的下一个节点是头节点,头节点的上一个节点是尾节点。1.单向循环链表:尾节点的指针域指向头结点的地址。2.单向循环链表的节点:数据域和指针域。3.双向链表节点的结构体定义。 阅读详情

相关推荐

[数据结构]链表之循环链表

需要注意的是,在循环链表中,插入和删除操作需要额外考虑最后一个节点的next指针和第一个节点的prev指针的修改。总之,循环链表是一种特殊的链表结构,在实现各种操作时需要注意其连续性和有序性,并针对特殊情况进行相应的处理。需要注意的是,在进行各种操作时,需要保证循环链表的连续性和有序性,以避免数据不一致等问题的发生。需要注意的是,在进行各种操作时,需要保证循环链表的连续性和有序性,即每个节点的next指针都指向下一个节点,并且最后一个节点的next指针指向头节点。但是,其实现简单,无需处理哈希冲突等问题。

beenles的博客 2743

循环链表的经典问题

在罗马人占领桥塔帕特之后,39人和约瑟夫以及他的朋友躲到一个山洞里,39个犹太人宁愿死,也不愿意被抓,于是他们想到一个自杀的方式:41人排成一圈,由第一个人开始报数,每数到三,该人就必须自杀,然后由下一个人再开始报数,直到所有人都自杀身亡为止。怎样安排顺序才能让约瑟夫和他的朋友活到最后呢?这是一个循环链表的经典问题顺便将之前学的不太扎实的链表的创建、元素删除一并练习了#include<stdio.h

qq_924070845的博客 526

Java中的循环链表

与链表相比,循环链表略有不同。在循环链表中,最后一个节点指向第一个节点,从而完成一整圈节点。换句话说,我们也可以说在这个链表中,最后一个元素不是空的。在这种类型的链表中,任何节点都可以作为起点。这意味着可以遍历整个列表,即使我们从任何节点开始。当最后一个节点指向第一个节点时,在循环链表中执行排队和出列操作非常容易。在本文中,我们将通过示例了解循环链表。Java中循环链表的语法:以下是语法:节点类定义语法- public class Course{ float marksscored; Course comi

JavaMonsterr的博客 1556

C++ list插入元素源码分析及过程图

插入过程源码: template<class... _Valty> void _Insert(_Unchecked_const_iterator _Where, _Valty&&... _Val) { // insert element at _Where _Nodeptr _Pnode = _Where._Mynode(); _Nodeptr _...

Cosmopolitan的博客 466

PYNQ-Z2 开发板从镜像烧录到 Jupyter 交互全流程指南

本文详细介绍了PYNQ-Z2开发板从镜像烧录到Jupyter交互的全流程指南,包括硬件解析、镜像烧录技巧、设备启动与网络配置、Jupyter Notebook深度使用以及实战案例分享。通过具体步骤和实用技巧,帮助开发者快速上手PYNQ-Z2开发板,实现高效的FPGA开发和智能家居控制应用。

weixin_28736355的博客 438

西门子1500 PLC与巴鲁夫RFID实战:从硬件接线到数据读写的完整流程

本文详细介绍了西门子S7-1500 PLC与巴鲁夫RFID系统集成的完整实战流程。内容涵盖从硬件选型、接线、PROFINET网络配置,到在TIA Portal中安装GSD文件、组态设备、分配地址,再到使用标准功能块(如FB31)进行程序架构设计、实现数据读写以及错误诊断。文章重点分享了硬件连接要点、软件配置步骤、数据块管理技巧以及调试中常见问题的解决方案,为工业自动化工程师实施RFID项目提供了清晰的指导。

weixin_29161785的博客 385

Python数据结构之循环单链表

Python数据结构之循环单链表 前言 ​  单链表的另一常见变形是循环单链表(简称循环链表),其中最后一个结点的next域不用None,而是指向表的第一个结点,但是如果仔细考虑链表对象记录表尾结点更加重要.这样可以同时支持时间复杂度O(1)的表头/表尾插入和删除操作. 循环链表的基本操作 创建结点 代码 class Node: """ 定义node节点 """ ...

张先生-您好的博客 1133

ONNC Open Neural Network Compiler 开源神经网络编译器 一个 开源、模块化、可重用编译器算法和工具链的库,专门针对深度学习加速器(DLA)部署导入ONNX模型

ONNC是一个集合了开源、模块化、可重用编译器算法和工具链的库,专门针对深度学习加速器(DLA)。ONNC从底层开始构建,旨在将ONNX中间表示(IR)翻译成专有DLA代码。其软件架构设计强调可移植性和可重用性,从而简化了开发新后端的工作。上图展示了ONNC软件栈的顶层框图。软件栈从导入ONNX计算图模型到输出相应的硬件二进制文件,展示了各个功能块。

万有文的博客 1992

四道有趣的单链表面试题(单链表反序、找出链表的中间元素、链表排序、判断一个单链表是否有环)

参考:http://blog.sina.com.cn/s/blog_725dd1010100tr4y.html 四道有趣的单链表面试题(单链表反序、找出链表的中间元素、链表排序、判断一个单链表是否有环) 以下给出链表结点的数据结构: template struct LinkNode{   //链表节点 T data; LinkNode* link; LinkNode(LinkNod

行走的天马 1128

海康Visionmaster-通讯管理:ModBus 通信发送非整型 数据的方法

海康Visionmaster-通讯管理:ModBus 通信发送非整型 数据的方法

视觉人机器视觉的博客 1741

「JS逆向三百例」JS逆向HIKVISION-视频监控的前端密码加密

本文详细分析了HIKVISION-海康威视监控前端登录过程中密码的加密机制,通过逆向工程解析了其 JavaScript 加密逻辑,重点研究了HIKVISION-海康威视监控的前端密码SHA256加密算法的实现。基于逆向分析结果,使用 Python 模拟了HIKVISION-海康威视监控的登录流程,最终实现了自动化登录功能。本文旨在为安全研究人员提供技术参考,帮助理解前端加密机制,并强调技术研究的合法性和合规性。

布啦啦 1096

leetcode刷题总结--链表问题(python)双指针法

链表中的双指针问题(python)

vinojie的博客 620

Redhawk:什么是timing window?

STA timing file中timing window的作用和计算方式

m0_61544122的博客 1万+

【循环链表】数据结构——单向循环链表和双向循环链表操作&笔记

一、单向循环链表 将单链表的首尾节点相连就形成了单向循环链表。 1、单向循环链表的节点 2、单向循环链表的结构 单向循环链表只有一个节点时: 二、双向循环链表 1、双向循环链表示意图 2、双向循环链表节点设计 struct d_node{ int data; //数据域 struct d_node *next; struct d_node *prev; }; 3、双向循环链表的一般性结构 1)只有头结点的情况 2)有多个节点的情况 4、双向循环链表头插法插入节点 步骤: 1)p-&

皮皮不调皮的博客 9601

【知识分享】IBIS 建模指南 04

文章详细阐述了将缓冲器数据转换为IBIS模型格式的核心步骤与规范要求。主要内容包括:1)IBIS文件三大结构(文件头信息、组件引脚映射、缓冲器行为描述)及其关键词定义;2)四种关键I-V表(上下拉、电源/地钳位)的数据处理规则,强调需避免重复计算效应;3)切换特性描述方法,指出V-T波形表优于Ramp数据的三大优势;4)差分缓冲器通过[DiffPin]关键词实现建模的特殊流程。文中特别强调数据外推校验、参考电压基准转换、工艺角数据排序等易错环节的处理技巧,为创建符合IBIS 4.0规范的精确模型提供指导。

一只豌豆象的博客 2050

ImportError: DLL load failed: 找不到指定的程序的解决方案

本文主要介绍了ImportError: DLL load failed: 找不到指定的程序的解决方案,希望能对使用Python的同学们有所帮助。 文章目录 1. 问题描述 2. 解决方案

weixin_43178406的博客 18万+

单链表、循环链表、双向循环链表总结

链表介绍 不带头结点的单向链表 带头结点的单向链表 循环链表 双向循环链表

Keep Moving~ 8360

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

拿捏循环链表

其实地上本没有路,走的人多了也便成了路!

X_do_myself的博客 1656

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

单向循环链表改为双向循环链表

/* 单项循环链表改双向循环链表 data数据域,next后继结点指针域,prior前驱结点指针域 说明: 这里的链表带头结点 */ #include <iostream> #include <cstdlib> using namespace std; const int flag = -1; typedef struct SiLinkCirList{ int data; struct SiLinkCirList *next, *prior; }*List; //创建单向循环

qq_40659154的博客 3353

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

循环链表的创建

循环链表的创建以及基本操作 上篇我们讲了运用头插法和尾插法创建单链表的方法,和两种方法的比较。 接着我们学习循环链表的创建。 只要学会了单链表的创建,循环链表的创建就变得很简单。 循环链表创建 单链表的结构: 循环链表: 所谓循环链表,就是将单链表的尾结点 end 的指针域 也就是 end->next 指向头结点的地址 : end->next = head 。 这样就完成了循环链表的创建。 这就完了? 当然没有那么简单了~~~ 循环链表不同于单链表,原因在于上篇我们讲单链表的时候,尾结点指针域

lhh_qrsly的博客 5068

数据结构——循环链表

循环链表的简单操作

zhang_ysx的博客 5805

单向循环链表和双向循环链表

单向循环链表和双向循环链表1.单向循环链表2.双向循环链表 关于顺序表、单向链表和双向链表请将鼠标移步 此处点击 1.单向循环链表 代码实现: //#pragma once //作为头文件时加上这行 #include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef int DataType; t...

指弹键盘哼民谣 2482

JS 循环链表

循环链表是一种特殊的链表数据结构,其中最后一个节点指向链表的头节点,形成一个循环的环状结构。创建链表节点对象,通过赋值和指针操作来构建循环链表,并确保最后一个节点的指针指向头节点,形成循环。需要额外指针:与普通链表相比,循环链表需要额外的指针来记录链表的尾节点(即最后一个节点)或提供便捷访问的起点节点。在 JavaScript 中,循环链表是一种特殊的链表结构,其中最后一个节点指向头节点,形成一个循环。循环链表是一种链表的变体,其中链表中的最后一个节点指向链表的头节点,形成一个循环或环状结构。

肥晨开发的学习之路 1296

C++循环链表

C++循环链表 单向循环链表和单向链表的区别: (1)单向链表为头指针,循环链表为尾指针,头指针指向头结点,尾指针指向终端结点; (2)为统一方便操作,单向链表设置头结点,单向循环链表设置头结点和尾结点; (3)设置尾结点后,尾指针指向尾结点,插入,删除等操作不用移动尾指针。 在单向链表中,链表最后一个结点的next指针指向NULL,而所谓的循环链表就是将最后一个结点本来指向空的改变其指...

King逍灬遥 3818

不带头结点的双向循环链表

基本概念 循环链表:将单链表中最后一个结点的next指向头结点或者空指针,就使得整个单链表形成一个环,这种头尾相接的单链表称为单循环链表,简称循环链表。 双向链表:是在单链表的每个结点中,再设置一个指向其前驱结点的指针域prior,在双向链表的结点中有两个指针域,一个next指向直接后继,一个prior指向直接前驱。 双向循环链表:将二者结合起来,结点有两个指针域,且最后一个结点的next指向...

cherry的博客 5390
上一篇: 从B 树、B+ 树、B* 树谈到R 树 --- 先转了 正复习着ds 呢
下一篇: C++ new 和 delete 的重载
lsff01
博客等级 码龄14年 4粉丝 33原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值