Linux-C学习笔记-循环链表

14 篇文章 0 订阅
12 篇文章 0 订阅

学完了单链表,循环链表当然得学习

循环链表与单链表的区别就在于单链表最后一个节点的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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值