学完了单链表,循环链表当然得学习
循环链表与单链表的区别就在于单链表最后一个节点的next指针指向NULL,而循环链表的最后一个节点的next指针指向第一个数据节点
以下是循环链表的头文件、实现文件及测试文件,适用于任何类型的数据节点
/********************************************************************************************************/
file : CircleList.h
#ifndef _CIRCLELIST_H_
#define _CIRCLELIST_H_
typedef void CircleList;
typedef void CircleListNode;
extern CircleList* CircleList_Create();
extern void CircleList_Destroy(CircleList* list);
extern void CircleList_Clear(CircleList* list);
extern int CircleList_Length(CircleList* list);
extern int CircleList_Insert(CircleList* list, CircleListNode* node, int pos);
extern CircleListNode* CircleList_Get(CircleList* list, int pos);
extern CircleListNode* CircleList_Delete(CircleList* list, int pos);
extern void CircleList_Reverse(CircleList* list);
#endif
/********************************************************************************************************/
file : CircleList.c
/**************************************************************************
* 文件名 : CircleList.c
* 文件说明 :本文件是循环链表的实现函数,包括链表创建,删除,清空,获取链表长度,
* 获取链表结点,删除链表结点,链表逆序操作,适用于任意类型的数据结点,
* 使用时传入数据结点指针,及其他参数即可
**************************************************************************/
//库文件包含
#include <stdio.h>
#include <malloc.h>
//本地头文件包含
#include "CircleList.h"
//结构体定义
//封装数据结点定义
typedef struct _tag_TCircleListNode TCircleListNode;
struct _tag_TCircleListNode
{
unsigned int addr; //数据结点地址保存区
TCircleListNode* next; //链表指针
};
//封装链表头结点
typedef struct _tag_TCircleList
{
int length; //链表长度
TCircleListNode* header; //链表头指针
}TCircleList;
//函数实现
/*********************************************************************************
* 函数原型:CircleList* CircleList_Create()
* 函数说明:创建循环链表
* 参数说明:输入参数:无
* 输出参数:无
* 返回值:CircleList* 循环链表指针
*********************************************************************************/
CircleList* CircleList_Create()
{
//申请头结点空间
TCircleList* ret = (TCircleList*)malloc(sizeof(TCircleList));
if(ret != NULL)
{
ret->length = 0; //循环链表长度初始化
ret->header = NULL; //循环链表头结点指针初始化
}
return (CircleList*)ret; //返回循环链表指针
}
/*********************************************************************************
* 函数原型:void CircleList_Destroy(CircleList* list)
* 函数说明:删除循环链表
* 参数说明:输入参数:CircleList* list 循环链表指针
* 输出参数:无
* 返回值:无
*********************************************************************************/
void CircleList_Destroy(CircleList* list)
{
CircleList_Clear(list); //清空循环链表
free((TCircleList*)list); //释放头结点空间
list = NULL; //清空链表指针
}
/*********************************************************************************
* 函数原型:void CircleList_Clear(CircleList* list)
* 函数说明:循环链表清空
* 参数说明:输入参数:CircleList* list 循环链表指针
* 输出参数:无
* 返回值:无
*********************************************************************************/
void CircleList_Clear(CircleList* list)
{
TCircleList* sList = (TCircleList*)list;
//链表指针非空且链表有数据结点才可清空
if(sList != NULL && sList->header != NULL)
{
//从编号为1(编号从0开始)的结点开始删除
TCircleListNode* pList = sList->header;
while(pList->next != sList->header)
{
pList = sList->header->next;
sList->header->next = pList->next;
free(pList);
sList->length--;
pList = sList->header;
}
//删除剩余的编号为0的结点
free(pList);
sList->header = NULL;
sList->length--;
}
}
/*********************************************************************************
* 函数原型:int CircleList_Length(CircleList* list)
* 函数说明:获取单链表长度
* 参数说明:输入参数:CircleList* list 循环链表指针
* 输出参数:无
* 返回值:获取失败返回-1
* 获取成功返回非负数(单链表当前长度)
************************************************************************/
int CircleList_Length(CircleList* list)
{
int ret = -1;
TCircleList* sList = (TCircleList*)list;
if(sList != NULL)
{
ret = sList->length;
}
return ret;
}
/*********************************************************************************
* 函数原型:int CircleList_Insert(CircleList* list, CircleListNode* node, int pos)
* 函数说明:向循环链表中插入结点
* 参数说明:输入参数:CircleList* list 循环链表指针
* CircleListNode* node 待插入链表数据地址
* int pos 插入位置,从0开始
* 输出参数:无
* 返回值:获取失败返回假(0)
* 获取成功返回真(1)
*********************************************************************************/
int CircleList_Insert(CircleList* list, CircleListNode* node, int pos)
{
int i = 0;
TCircleList* sList = (TCircleList*)list;
int ret = (sList != NULL) && (pos >= 0) && (node != NULL); //检查链表
if(ret)
{
//申请数据结点空间
TCircleListNode* pNew = (TCircleListNode*)malloc(sizeof(TCircleListNode));
if(pNew != NULL)
{
//保存数据
pNew->addr = (unsigned int)node;
//链表为空时默认插入0号位置
if(pos == 0 || sList->header == NULL)
{
pNew->next = sList->header;
sList->header = pNew;
if(pNew->next == NULL)
{
pNew->next = sList->header;
}
else
{
TCircleListNode* last = pNew->next;
while(pNew->next != last->next)
{
last = last->next;
}
last->next = pNew;
}
}
//链表不为空且插入位置不是编号为0的位置
else
{
TCircleListNode* current = sList->header;
for(i = 1; (i < pos) && (current->next != NULL); i++)
{
current = current->next;
}
pNew->next = current->next;
current->next = pNew;
}
//链表长度加1
sList->length++;
}
else
{
ret = 0;
}
}
return ret;
}
/*********************************************************************************
* 函数原型:CircleListNode* CircleList_Get(CircleList* list, int pos)
* 函数说明:获取链表中编号为pos的数据
* 参数说明:输入参数:CircleList* list 循环链表指针
* int pos 获取编号,从0开始
* 输出参数:无
* 返回值:CircleListNode* 链表数据地址,为空表示获取失败
*********************************************************************************/
CircleListNode* CircleList_Get(CircleList* list, int pos)
{
int i = 0;
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL;
//判断链表是否合法,判断获取位置是否合法
if( (sList != NULL) && (0 <= pos) )
{
//修正获取位置
pos = pos % sList->length;
if(0 == pos)
{
//获取编号为0的数据地址
ret = (CircleListNode*)(sList->header->addr);
}
else
{
//获取编号大于0的数据地址
TCircleListNode* current = sList->header;
for(i=1; i<pos; i++)
{
current = current->next;
}
ret = (CircleListNode*)(current->next->addr);
}
}
return ret;
}
/*********************************************************************************
* 函数原型:CircleListNode* CircleList_Delete(CircleList* list, int pos)
* 函数说明:删除链表中编号为pos的数据,并将其返回
* 参数说明:输入参数:CircleList* list 循环链表指针
* int pos 获取编号,从0开始
* 输出参数:无
* 返回值:CircleListNode* 链表数据地址,为空表示删除失败
*********************************************************************************/
CircleListNode* CircleList_Delete(CircleList* list, int pos)
{
TCircleList* sList = (TCircleList*)list;
CircleListNode* ret = NULL;
int i = 0;
//判断链表是否合法,判断删除位置是否合法
if( (sList != NULL) && sList->length > 0 && (0 <= pos) )
{
TCircleListNode* current = sList->header;
//修正获取编号
pos = pos % sList->length;
if(0 == pos)
{
//删除编号为0的数据结点
ret = (CircleListNode*)(sList->header->addr);
sList->header = current->next;
current = sList->header;
while(current->next->next != sList->header)
{
current = current->next;
}
free(current->next);
current->next = sList->header;
//删除后链表长度为0,即链表为空
if(--sList->length == 0)
{
//链表头数据结点指针复位
sList->header = NULL;
}
}
else
{
//删除编号大于0的数据结点
TCircleListNode* fList = NULL;
for(i=1; i < pos; i++)
{
current = current->next;
}
ret = (CircleListNode*)(current->next->addr);
fList = current->next;
current->next = current->next->next;
free(fList);
sList->length--;
}
}
return ret;
}
#if 0
/*********************************************************************************
* 函数原型:void CircleList_Reverse(CircleList* list)
* 函数说明:循环链表逆序:通过修改指针方式实现
* 参数说明:输入参数:CircleList* list 循环链表指针
* 输出参数:无
* 返回值:无
*********************************************************************************/
void CircleList_Reverse(CircleList* list)
{
TCircleList* sList = (TCircleList*)list;
//链表长度为2时,直接移动头结点指针实现逆序
if(sList->length == 2)
{
sList->header = sList->header->next;
}
//链表长度大于2,依次修改指针
else if(sList->length > 2)
{
TCircleListNode* p1 = sList->header->next;
TCircleListNode* p2 = p1->next;
sList->header->next = NULL;
while(p2 != NULL)
{
p1->next = sList->header;
sList->header = p1;
p1 = p2;
p2 = p2->next;
}
p1->next = sList->header;
}
}
#else
/*********************************************************************************
* 函数原型:void CircleList_Reverse(CircleList* list)
* 函数说明:循环链表逆序:通过新建循环链表方式实现,将原链表按头删法依次删除,并将
删除结点重新按照头插法插入新链表最后将新链表交给原链表指针
* 参数说明:输入参数:CircleList* list 循环链表指针
* 输出参数:
* 返回值:无
*********************************************************************************/
void CircleList_Reverse(CircleList* list)
{
TCircleList* sList = (TCircleList*)list;
//链表长度不小于2,启动逆序
if(sList->length >= 2)
{
TCircleListNode* newHead = NULL;
TCircleListNode* newLast = NULL;
while(sList->header!= sList->header->next)
{
//删除原链表中编号为1(编号从0开始)的节点,将其保存在临时指针p中
TCircleListNode* p = sList->header->next;
sList->header->next = sList->header->next->next;
//临时链表为空,添加第一个结点
if(newHead == NULL)
{
newHead = p;
p->next = newHead;
newLast = p;
}
//添加结点到临时链表
else
{
p->next = newHead;
newHead = p;
newLast->next = newHead;
}
}
//将原链表编号为0的节点插入临时链表尾部
sList->header->next = newLast->next;
newLast->next = sList->header;
//逆序链表保存
sList->header = newHead;
}
}
#endif
/*********************************************************************************************************************/
file : main.c 测试代码,适用于任何类型的数据节点
#include <stdio.h>
#include <stdlib.h>
#include "CircleList.h"
#define TEST_NUM 5
char Test_Data[10] = {'0','1','2','3','4','5','6','7','8','9'};
int main(int argc, char *argv[])
{
int index = 0;
CircleList* list = CircleList_Create();
printf(" Length Before Insert = %d\n", CircleList_Length(list));
for(index = 0; index < TEST_NUM - 2; index ++)
{
CircleList_Insert(list, Test_Data+index, 0);
}
printf(" Length After Insert and Before Clear = %d\n", CircleList_Length(list));
CircleList_Clear(list);
printf(" Length After Clear and Before Insert again = %d\n", CircleList_Length(list));
for(index = 0; index < TEST_NUM; index ++)
{
CircleList_Insert(list, Test_Data+index, 0);
}
printf("After Insert and Reverse Delete:\n");
for(index = 0; index < CircleList_Length(list); index ++)
{
printf("%c\n", *(char *)CircleList_Get(list, index));
}
printf("Delete:\n");
CircleList_Reverse(list);
printf("After Reverse and Before Delete:\n");
for(index = 0; index < CircleList_Length(list); index ++)
{
printf("%c\n", *(char *)CircleList_Get(list, index));
}
printf("Delete:\n");
for(index = 0; index < TEST_NUM/2; index ++)
{
printf("%c\n", *(char *)CircleList_Delete(list, 0));
}
printf("After Delete:\n");
for(index = 0; index < CircleList_Length(list); index ++)
{
printf("%c\n", *(char *)CircleList_Get(list, index));
}
printf("Destroy:\n");
CircleList_Destroy(list);
printf("Test Complete.\nPlease Input a char to Quit :");
Test_Data[0] = getchar();
return 0;
}