4--循环链表

1、基本概念

循环链表的定义:将单链表中最后一个数据元素的next指针指向第一个元素

循环链表拥有单链表的所有操作:

创建链表

销毁链表

获取链表长度

清空链表

获取第pos个元素操作

插入元素到位置pos

删除位置pos处的元素

游标的定义

在循环链表中可以定义一个“当前”指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。

循环链表新操作:

获取当前游标指向的数据元素

将游标重置指向链表中的第一个数据元素

将游标移动指向到链表中的下一个数据元素

直接指定删除链表中的某个数据元素

2、设计与实现

插入元素的分析

  1. 普通位置插入元素
  2. 添加第一个元素(第一次插入元素
  3. 最后一个位置插入元素
  4. 第一个位置插入元素(如图):

添加第一个元素如图:

在最后一个位置插入元素如图:

删除节点

3、优点和缺点

优点:功能强了。循环链表只是在单链表的基础上做了一个加强,循环链表可以完全取代单链表的使用,循环链表的Next和Current操作可以高效的遍历链表中的所有元素

缺点:代码复杂度提高了

约瑟夫问题-循环链表典型应用

n 个人围成一个圆圈,首先第 1 个人从 1 开始一个人一个人顺时针报数,报到第 m 个人,令其出列。然后再从下一个人开始从 1 顺时针报数,报到第 m 个人,再令其出列,…,如此下去,求出列顺序。

CircleList.h 

#ifndef _CIRCLELIST_H_

#define _CIRCLELIST_H_

typedef void CircleList;

/*

typedef struct _tag_CircleListNode CircleListNode;

struct _tag_CircleListNode

{

CircleListNode* next;

};

*/

typedef struct _tag_CircleListNode

{

 struct _tag_CircleListNode * next;

}CircleListNode;

CircleList* CircleList_Create();

void CircleList_Destroy(CircleList* list);

void CircleList_Clear(CircleList* list);

int CircleList_Length(CircleList* list);

int CircleList_Insert(CircleList* list, CircleListNode* node, int pos);

CircleListNode* CircleList_Get(CircleList* list, int pos);

CircleListNode* CircleList_Delete(CircleList* list, int pos);

//add

CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node);

CircleListNode* CircleList_Reset(CircleList* list);

CircleListNode* CircleList_Current(CircleList* list);

CircleListNode* CircleList_Next(CircleList* list);

#endif
CircleList.c

#include <stdio.h>

#include <malloc.h>

#include "CircleList.h"

typedef struct _tag_CircleList

{

 CircleListNode header;

 CircleListNode* slider;

 int length;

} TCircleList;

CircleList* CircleList_Create() // O(1)

{

 TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));

 if (ret == NULL)

 {

  return NULL;

 }

 ret->length = 0;

 ret->header.next = NULL;

 ret->slider = NULL;

 return ret;

}

void CircleList_Destroy(CircleList* list) // O(1)

{

 if (list == NULL)

 {

  return ;

 }

 free(list);

}

void CircleList_Clear(CircleList* list) // O(1)

{

 TCircleList* sList = (TCircleList*)list;

 if (sList == NULL)

 {

  return ;

 }

 sList->length = 0;

 sList->header.next = NULL;

 sList->slider = NULL;

}

int CircleList_Length(CircleList* list) // O(1)

{

 TCircleList* sList = (TCircleList*)list;

 int ret = -1;

 if (list == NULL)

 {

  return ret;

 }

 ret = sList->length;

 return ret;

}

int CircleList_Insert(CircleList* list, CircleListNode* node, int pos) // O(n)

{

 int ret = 0, i=0;

 TCircleList* sList = (TCircleList*)list;

 if (list == NULL || node== NULL || pos<0)

 {

  return -1;

 }

 //if( ret )

 {

  CircleListNode* current = (CircleListNode*)sList;

  for(i=0; (i<pos) && (current->next != NULL); i++)

  {

   current = current->next;

  }

  //current->next 0号节点的地址

  node->next = current->next; //1

  current->next = node; //2

  //若第一次插入节点

  if( sList->length == 0 )

  {

   sList->slider = node;

  }

  sList->length++;

  //若头插法

  if( current == (CircleListNode*)sList )

  {

   //获取最后一个元素

   CircleListNode* last = CircleList_Get(sList, sList->length - 1);

   last->next = current->next; //3

  }

 }

 return ret;

}

CircleListNode* CircleList_Get(CircleList* list, int pos) // O(n)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 int i = 0;

 if (list==NULL || pos<0)

 {

  return NULL;

 }

 //if( (sList != NULL) && (pos >= 0) && (sList->length > 0) )

 {

  CircleListNode* current = (CircleListNode*)sList;

  for(i=0; i<pos; i++)

  {

   current = current->next;

  }

  ret = current->next;

 }

 return ret;

}

CircleListNode* CircleList_Delete(CircleList* list, int pos) // O(n)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 int i = 0;

 if( (sList != NULL) && (pos >= 0) && (sList->length > 0) )

 {

  CircleListNode* current = (CircleListNode*)sList;

  CircleListNode* last = NULL;

  for(i=0; i<pos; i++)

  {

   current = current->next;

  }

  //若删除第一个元素

  if( current == (CircleListNode*)sList )

  {

   last = (CircleListNode*)CircleList_Get(sList, sList->length - 1);

  }

  //求要删除的元素

  ret = current->next;

  current->next = ret->next;

  sList->length--;

  //判断链表是否为空

  if( last != NULL )

  {

   sList->header.next = ret->next;

   last->next = ret->next;

  }

  //若删除的元素为游标所指的元素

  if( sList->slider == ret )

  {

   sList->slider = ret->next;

  }

  //若删除元素后,链表长度为0

  if( sList->length == 0 )

  {

   sList->header.next = NULL;

   sList->slider = NULL;

  }

 }

 return ret;

}

CircleListNode* CircleList_DeleteNode(CircleList* list, CircleListNode* node) // O(n)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 int i = 0;

 if( sList != NULL )

 {

  CircleListNode* current = (CircleListNode*)sList;

  //查找node在循环链表中的位置i

  for(i=0; i<sList->length; i++)

  {

   if( current->next == node )

   {

    ret = current->next;

    break;

   }

   current = current->next;

  }

  //如果ret找到,根据i去删除

  if( ret != NULL )

  {

   CircleList_Delete(sList, i);

  }

 }

 return ret;

}

CircleListNode* CircleList_Reset(CircleList* list) // O(1)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 if( sList != NULL )

 {

  sList->slider = sList->header.next;

  ret = sList->slider;

 }

 return ret;

}

CircleListNode* CircleList_Current(CircleList* list) // O(1)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 if( sList != NULL )

 {

  ret = sList->slider;

 }

 return ret;

}

CircleListNode* CircleList_Next(CircleList* list) // O(1)

{

 TCircleList* sList = (TCircleList*)list;

 CircleListNode* ret = NULL;

 if( (sList != NULL) && (sList->slider != NULL) )

 {

  ret = sList->slider;

  sList->slider = ret->next;

 }

 return ret;

}
#include <stdio.h>

#include <stdlib.h>

#include "CircleList.h"

struct Value

{

 CircleListNode header;

 int v;

};

void  main()

{

 int i = 0;

 CircleList* list = CircleList_Create();

 struct Value v1;

 struct Value v2;

 struct Value v3;

 struct Value v4;

 struct Value v5;

 struct Value v6;

 struct Value v7;

 struct Value v8;

 v1.v = 1;

 v2.v = 2;

 v3.v = 3;

 v4.v = 4;

 v5.v = 5;

 v6.v = 6;

 v7.v = 7;

 v8.v = 8;

 CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v2, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v3, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v4, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v5, 5);

 CircleList_Delete(list, 0);

 for(i=0; i<2*CircleList_Length(list); i++)

 {

  struct Value* pv = (struct Value*)CircleList_Get(list, i);

  printf("%d\n", pv->v);

 }

 printf("\n");

 while( CircleList_Length(list) > 0 )

 {

  struct Value* pv = (struct Value*)CircleList_Delete(list, 0);

  printf("%d\n", pv->v);

 }

 printf("\n");

 CircleList_Insert(list, (CircleListNode*)&v1, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v2, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v3, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v4, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v5, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v6, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v7, CircleList_Length(list));

 CircleList_Insert(list, (CircleListNode*)&v8, CircleList_Length(list));

 for(i=0; i<CircleList_Length(list); i++)

 {

  struct Value* pv = (struct Value*)CircleList_Next(list);

  printf("%d\n", pv->v);

 }

 printf("\n");

 CircleList_Reset(list);

 while( CircleList_Length(list) > 0 )

 {

  struct Value* pv = NULL;

  for(i=1; i<3; i++)

  {

   CircleList_Next(list);

  }

  pv = (struct Value*)CircleList_Current(list);

  printf("%d\n", pv->v);

  CircleList_DeleteNode(list, (CircleListNode*)pv);

 }

 CircleList_Destroy(list);

 system("pause");

 return ;

}
时间: 2024-10-12 20:41:34

4--循环链表的相关文章

循环链表

?? 循环链表和单链表没有本质上的区别.唯一不同的链表的最后不再是空的了,而是指向了first头指针.仅仅有这样我们才会实现链表的循环功能,那么问题来了,我们在以下的函数功能中我们仅仅是须要把里面用的头指针的重用名换到first->next中.并且当中的计数器count也从1開始计数,这样就避免了在while的循环中第一步实行不下去. 废话不多说. 具体看wo的代码吧. #ifndef CirLinkList_H #define CirLinkList_H #include<iostream&

第33课 双向循环链表的实现

1. DTLib中双向链表的设计思路 (1)数据结点之间在逻辑上构成双向循环,这有别于Linux内核链表的实现. (2)头结点仅用于结点的定位,而Linux内核链表是将头结点作为循环的一部分. 2. 实现思路 (1)通过模板定义DualCircleList类,继承自DualLinkList类 (2)在DualCircleList内部使用Linux内核链表进行实现(另类实现) (3)使用struct list_head定义DualCircleList的头结点 (4)特殊处理:循环遍历时忽略头结点

C++__循环链表(练习)

循环链表 link.h #ifndef LINK_H_ #define LINK_H_ #define HEADER 0 #define TAIL -1 typedef int data_type; enum LINK_OP { LINK_ERR = -1, LINK_OK }; class LINK { private: data_type data; LINK *next; LINK *last; public: LINK(); LINK(data_type data); virtual ~

双向循环链表 初始化 插入 删除

#include <stdio.h> #include <stdlib.h> #define OK 1 #define ERROR -1 #define TRUE 1 #define FALSE -1 #define NULL 0 #define OVERFLOW -2 #define ElemType int #define Status int typedef int ElemType typedef int Status #define LEN sizeof(DuLNode)

循环链表的基本操作

循环链表与普通链表最大的区别在于尾结点的指针域指向什么:普通链表的尾结点的指针域指向空(NULL),而循环链表的尾结点的指针域指向头结点,形成一个环! #include<iostream> #include<cstdlib> using namespace std; struct Node{ int data; Node* next; }; typedef Node* LinkList; //函数声明 void show(); void InitList(LinkList &

(线性结构)循环链表的初始化,增删减除结点。新手的了解

1.查找rear指针为O(1) 那么开始节点就为rear->next->next,也是O(1)   //大家可以想象从最后一个结点开始有什么好处2.head->next ==head 判断是否空表 //链表的定义 typedef struct CLinkList { ElemType data; struct CLinkList; } node ; 1 //插入结点 2 void ds_insert (node **pNode,int i) 3 { 4 node *temp; 5 nod

双向循环链表

//双向循环链表 typedef int datatype; //方便修改 //当然也可以写成模板来适应更多的数据类型 struct dclink{ datatype data;//数据定义 struct dclink *pre; struct dclink *next;//前驱和后继指针 }; class DCLink { public: DCLink();//default constructor DCLink(datatype data);//单参constructor void add(

算法导论13:双向循环链表 2016.1.13

今天这个又打了很长时间,本来觉得数据结构就是那样,不过是一种思维,但是实际上真正自己打和想象中差距还是很大,需要考虑到各种细节. 今天这个问题有一个比较有意思的应用,就是“约瑟夫环问题”. 具体可以参见百度百科: http://baike.baidu.com/link?url=poA1Aanlptc6yzP1puYhSw_0RQjRAplhPfHwk6eoiqMNxw6WigCEbexxZ8a9SUbrMGokpPbKNzVYw308xjeEw_ 读完问题就可以发现,这个问题用链表就是一个很完美

循环链表模板

#include <stdio.h> #include <stdlib.h> typedef struct lnode{ int data; struct lnode* next; } node,*linklist; void initlist(linklist &l){ linklist p=(linklist)malloc(sizeof(node)); p->next=p;//此处可以控制循环链表 l=p; } void InsertFront(linklist

链表(五)——单向循环链表

1.单向循环链表 区分单向链表和单向循环链表:单向循环链表的尾指针指向头结点. 2.单向循环链表的基本操作 #include <stdio.h> #include <malloc.h> #define NULL 0 typedef struct node { int data; struct node *next; }ElemSN; ElemSN * creat_link(int ms); //创建一个单向循环链表 void print_link(ElemSN *head); //