循环链表设计与API实现
循环链表的定义:将单链表中最后一个数据元素的next指针指向第一个元素。
新增功能:游标的定义
在循环链表中可以定义一个“当前”指针,这个指针通常称为游标,可以通过这个游标来遍历链表中的所有元素。
优点:功能强了,
循环链表只是在单链表的基础上做了一个加强,
循环链表可以完全取代单链表的使用,
循环链表的Next和Current操作可以高效的遍历链表中的所有元素.
缺点:
代码复杂度提高了.
circlelist.h
#ifndef __MYCIRCLELIST_H__
#define __MYCIRCLELIST_H__
//传统链表 数据和指针在一个节点
//现代链表 把指针独立出来,做成节点 在包含数据的节点中包含这个独立节点
typedef void CircleList;
typedef struct _tag_CircleListNode//被大千世界包含
{
struct _tag_CircleListNode*next;
}CircleListNode;
CircleList* CircleList_Create();
int 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 <stdlib.h>
#include <string.h>
#include "circlelist.h"
//头结点 封装了一个 节点、游标和链表长度
typedef struct _tag_CircleList
{
CircleListNode header;
CircleListNode*slider;
int length;
}TCircleList;
CircleList* CircleList_Create()//创建头结点
{
TCircleList *ret = NULL;
ret = (TCircleList *)malloc(sizeof(TCircleList)) ;
memset(ret,0,sizeof(TCircleList));//等价于下面两句
//tmp->length = 0;
//tmp->header.next = NULL;
return ret;//任何类型的指针都可以直接赋值给void*
}
int CircleList_Destroy(CircleList* list)
{
if (list!=NULL)
{
free(list);
list = NULL;
}
else
{
return -1;
}
}
//让链表恢复到初始化状态
void CircleList_Clear(CircleList* list)
{
TCircleList *tlist = NULL;
if (list==NULL)
{
return ;
}
tlist = (TCircleList *)list;//void*类型的指针必须转换后赋值给其他类型的指针
tlist->length = 0;
tlist->header.next = NULL;
tlist->slider = NULL;
}
int CircleList_Length(CircleList* list)
{
TCircleList *tlist = NULL;
if (list==NULL)
{
return 0;
}
tlist = (TCircleList *)list;//void*类型的指针先转换再赋值给相应类型的指针
return tlist->length;
}
int CircleList_Insert(CircleList*list,CircleListNode*node,int pos)
{
int ret = 0,i;
CircleListNode*current=NULL;
TCircleList *tList = NULL;
if (list ==NULL||node==NULL||pos<0)
{
ret = -1;
printf("func CircleList_Insert() error :%d\n ",ret);
return ret;
}
tList = (TCircleList*)list;//void类型的指针需要转换后赋值给相应的指针类型数据
current = &tList->header;
for (i=0;i<pos&&(current->next!=NULL);i++)
{
current = current->next;
}
node->next = current->next;
current->next = node;
//如果第一次插入节点 让游标指向0号位置
if (tList->length==0)
{
tList->slider = node;
}
tList->length++;
//若是头插法(在0号位置插) 应该让尾部节点的next指向刚插入的节点 循环!!
//若是尾插法 应该让第一个插入的结点的next指向自己 随后能保证刚插入的元素指向0号位置的结点
//通过这个地方的判断可以保证无论是头插法 还是尾插法 都能保证该链表是循环链表
//原因: 一开始 current指向头结点 跳0步 没跳动 还是指向头结点
if (current == (CircleListNode*)tList)
{
CircleListNode* last = CircleList_Get(tList,tList->length-1);
last->next = current->next;
}
return ret;
}
CircleListNode* CircleList_Get(CircleList*list,int pos)
{
int ret = 0,i;
CircleListNode*current=NULL;
TCircleList *tList = NULL;
if (list ==NULL||pos<0)
{
ret = -1;
printf("func CircleList_Get() error :%d\n ",ret);
return NULL;
}
tList = (TCircleList*)list;
current = &tList->header;//辅助指针变量指向链表头部
for (i=0;i<pos&&(current->next!=NULL);i++)
{
current = current->next;
}
return current->next;
}
//删除节点
CircleListNode* CircleList_Delete(CircleList*list,int pos)
{
int i;
CircleListNode*current=NULL;
CircleListNode*last=NULL;
CircleListNode*ret=NULL;
TCircleList *tList = NULL;
if (list ==NULL||pos<0)
{
printf("func CircleList_Delete() error\n");
return NULL;
}
tList = (TCircleList*)list;
current =(CircleListNode*)(&(tList->header));//辅助指针变量指向链表头部
//current = (CircleListNode*)tList; //这行代码和上边一样
for (i=0;i<pos&&(current->next!=NULL);i++)
{
current = current->next;
}
//若要删除第一个节点(0号位置)
if (current == (CircleListNode*)tList)
{
//获取链表最后一个元素
last = (CircleListNode*) CircleList_Get(list,tList->length-1);
}
ret = current->next;//缓存即将删除的节点
current->next = ret->next;
tList->length--;
//判断链表是否为空
if (last!=NULL)
{
//不为空
//头结点指向原来的1号位置 1号位置变为0号位置
tList->header.next = ret->next;
last->next = ret->next;//首尾相接
}
//判断要删除的位置是否为游标指向的位置
if ( tList->slider == ret)
{
//游标下移
tList->slider = ret->next;
}
//若删除元素后 链表为空(长度为0)
if (tList->length == 0)
{
tList->header.next = NULL;
tList->slider = NULL;
}
return ret;
}
//add 循环链表新操作
/*直接指定删除链表中的某个数据元素*/
CircleListNode* CircleList_DeleteNode(CircleList*list,CircleListNode*node)
{
CircleListNode*ret=NULL;
TCircleList *tList = (TCircleList*)list;
CircleListNode*current=NULL;
int i =0;
if (list ==NULL)
{
printf("func CircleList_Delete() error\n");
return NULL;
}
current = (CircleListNode*)tList;
//在循环链表中查找node的位置
for (i=0;i<tList->length;i++)
{
if (current->next==node)
{
ret = current->next;//缓存
break;
}
current = current->next;
}
//如果找到
if ( ret != NULL )
{
CircleList_Delete(list,i);
}
return ret;
}
/*将游标重置指向链表中的第一个节点*/
CircleListNode* CircleList_Reset(CircleList*list)
{
TCircleList *tList = (TCircleList*)list;//void类型的指针需要转换后赋值给相应的指针类型数据
CircleListNode*ret =NULL;
if (list ==NULL)
{
printf("func CircleList_Reset() error\n ");
return NULL;
}
tList->slider = tList->header.next;
ret = tList->slider;
return ret;
}
/*获取当前游标指向的数据元素*/
CircleListNode* CircleList_Current(CircleList*list)
{
TCircleList *tList = (TCircleList*)list;//void类型的指针需要转换后赋值给相应的指针类型数据
CircleListNode *ret = NULL;
if (list ==NULL)
{
printf("func CircleList_Reset() error :list = null\n ");
return ret ;
}
ret = tList->slider;
return ret;
}
/*把游标指向的位置返回 并将游标下移*/
CircleListNode* CircleList_Next(CircleList*list)
{
CircleListNode *ret = NULL;
TCircleList *tList = (TCircleList*)list;//void类型的指针需要转换后赋值给相应的指针类型数据
if (list ==NULL)
{
printf("func CircleList_Reset() error :list = NULL\n ");
}
ret = tList->slider;
tList->slider = ret->next;
return ret;
}
test.c
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include<stdio.h>
#include <string.h>
#include "circlelist.h"
//现代链表:业务节点(大千世界)包含链表节点(我)
typedef struct SValue
{
CircleListNode listnode;
int value;
}SValue;
int main()
{
//创建一个线性表
CircleList* list= NULL;
int length ,ret,i;
SValue v1,v2,v3,v4,v5,v6;
SValue *tmp2 =NULL;
v1.value = 30;
v2.value = 32;
v3.value = 33;
v4.value = 34;
v5.value = 35;
v6.value = 36;
//创建并返回TCircleList类型的头结点
list = CircleList_Create();//任意类型的指针变量都可以直接辅助给void*
if (list == NULL)
{
return -1;
}
length = CircleList_Length(list);//TCircleList
printf("length:%d\n",length);
//头插入
/*
ret = CircleList_Insert(list,(CircleListNode*)&v1, 0);
ret = CircleList_Insert(list,(CircleListNode*)&v2, 0);
ret = CircleList_Insert(list,(CircleListNode*)&v3, 0);
ret = CircleList_Insert(list,(CircleListNode*)&v4, 0);
ret = CircleList_Insert(list,(CircleListNode*)&v5, 0);
ret = CircleList_Insert(list,(CircleListNode*)&v6, 0);*/
//尾部插入
ret = CircleList_Insert(list,(CircleListNode*)&v1, CircleList_Length(list));
ret = CircleList_Insert(list,(CircleListNode*)&v2, CircleList_Length(list));
ret = CircleList_Insert(list,(CircleListNode*)&v3, CircleList_Length(list));
ret = CircleList_Insert(list,(CircleListNode*)&v4, CircleList_Length(list));
ret = CircleList_Insert(list,(CircleListNode*)&v5, CircleList_Length(list));
ret = CircleList_Insert(list,(CircleListNode*)&v6, CircleList_Length(list));
length = CircleList_Length(list);
printf("length:%d\n",length);
//遍历(打印2遍证明循环链表)
for (i=0;i<2*CircleList_Length(list);i++)
{
SValue *tmp =(SValue *)CircleList_Get(list,i);
if (tmp==NULL)
{
return;
}
printf("%d\n",tmp->value);
}
/*将游标重置指向链表中的第一个数据元素*/
tmp2 =(SValue *) CircleList_Reset(list);
printf("游标重置:%d\n",tmp2->value);
/*将游标移动指向到链表中的下一个数据元素*/
tmp2 =(SValue *) CircleList_Next(list);
printf("游标下移:%d\n",tmp2->value);
/*将游标当前位置*/
tmp2 =(SValue *) CircleList_Current(list);
printf("游标当前:%d\n",tmp2->value);
/*将游标重置指向链表中的第一个数据元素*/
tmp2 =(SValue *) CircleList_Reset(list);
printf("游标重置:%d\n",tmp2->value);
printf("测试删除指定\n");
//通过值 删除节点
CircleList_DeleteNode(list,(CircleListNode*)&v6);
//遍历 看是否删除
for (i=0;i<CircleList_Length(list);i++)
{
SValue *tmp =(SValue *)CircleList_Get(list,i);
if (tmp==NULL)
{
return;
}
printf("%d\n",tmp->value);
}
//删除
while (CircleList_Length(list)>0)
{
SValue*tmp =(SValue*) CircleList_Delete(list,0);
if (tmp==NULL)
{
return ;
}
//printf("delete : %d\n",tmp->value);
}
//销毁
ret = CircleList_Destroy(list);
system("pause");
return 0;
}