循环链表API

循环链表设计与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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值