循环链表——设计与实现

1.标准的循环链表与一般链表多了个游标,多了3个游标操作函数。

2.循环链表API的写法与一般链表大致一样,只有0号节点的增加和删除需要注意,还有一次节点的插入和最后一个节点的删除需要注意,删除时游标的移动需要注意。

3.循环链表相对于一般链表并无多大性能上的增强,只是让链表解决约瑟夫问题十分方便。

下面给出代码:

(代码看似复杂,只需要需要配合画图分析就可理解)

CircleList.h

#ifndef __CIRCLELIST_H__
#define __CIRCLELIST_H__

typedef void CircleList;
typedef struct CircleListNode{
	struct CircleListNode *next;
}CircleListNode;

//与一般链表相同的API
CircleList* CircleList_Create();
void CircleList_Destory(CircleList *list);
int CircleList_Length(CircleList *list);
void CircleList_Clear(CircleList *list);
int CircleList_Insert(CircleList *list, CircleListNode *node, int pos);
CircleListNode* CircleList_Delete(CircleList *list, int pos);
CircleListNode* CircleList_Get(CircleList *list, int pos);

//因为游标增加的API
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;
	int length;
	CircleListNode *slider;
}TCircleList;


CircleList* CircleList_Create()
{
	TCircleList *tlist;
	tlist = (TCircleList *)malloc(sizeof(TCircleList));
	if(NULL == tlist)
	{
		printf("CircleList_Create err (NULL == tlist)\n");
		return NULL;
	}
	memset(tlist, 0, sizeof(TCircleList));
	return tlist;
}
void CircleList_Destory(CircleList *list)
{
	TCircleList *tlist;
	if(NULL == list)
	{
		printf("CircleList_Destory err (NULL == list)\n");
		return;
	}
	tlist = (TCircleList *)list;
	free(tlist);
	tlist = NULL;
	return ;
}
int CircleList_Length(CircleList *list)
{
	TCircleList *tlist;
	if(NULL == list)
	{
		printf("CircleList_Length err (NULL == list)\n");
		return -1;
	}
	tlist = (TCircleList *)list;
	return tlist->length;
}
void CircleList_Clear(CircleList *list)
{
	TCircleList *tlist;
	if(NULL == list)
	{
		printf("CircleList_Clear err (NULL == list)\n");
		return;
	}
	tlist = (TCircleList *)list;
	memset(tlist, 0, sizeof(TCircleList));
	return ;
}
int CircleList_Insert(CircleList *list, CircleListNode *node, int pos)
{
	TCircleList *tlist;
	CircleListNode *current, *last;
	int i;
	if(NULL == list || NULL == node || pos < 0)
	{
		printf("CircleList_Insert err (NULL == list || NULL == node || pos < 0)\n");
		return -1;
	}
	tlist = (TCircleList *)list;
	if(pos > tlist->length)
		pos = tlist->length;
	current = &tlist->header;
	for(i = 0; i < pos; i++)
		current = current->next;
	node->next = current->next;
	current->next = node;
	tlist->length++;
	if(&tlist->header == current)
	{
		last = CircleList_Get(list, tlist->length - 1);
		last->next = node;
	}
	if(node->next == node)
		tlist->slider = node;

	return 0;
}
CircleListNode* CircleList_Delete(CircleList *list, int pos)
{
	TCircleList *tlist;
	CircleListNode *current, *last = NULL, *node;
	int i;
	if(NULL == list || pos < 0)
	{
		printf("CircleList_Delete err (NULL == list || pos < 0)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;
	if(pos >= tlist->length)
		pos = tlist->length -1;
	current = &tlist->header;
	for(i = 0; i < pos; i++)
		current = current->next;
	node = current->next;
		//如果删除的是0号节点,那么提前布局找到last节点
	if(current == &tlist->header)
		last = CircleList_Get(list, tlist->length -1);

	current->next = node->next;
	tlist->length--;
	if(tlist->slider == node)
		tlist->slider = node->next;

	if(last != NULL)
	{
		last->next = current->next;
	}

	//链表只有一个节点
	if(last == node)
	{
		memset(tlist, 0, sizeof(TCircleList));
	}

	return node;
}
CircleListNode* CircleList_Get(CircleList *list, int pos)
{
	TCircleList *tlist;
	CircleListNode *current, *last = NULL, *node;
	int i;
	if(NULL == list || pos < 0)
	{
		printf("CircleList_Get err (NULL == list || pos < 0)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;
	if(pos >= tlist->length)
	{
		printf("CircleList_Get err (pos >= tlist->length)\n");
		return NULL;
	}
	current = &tlist->header;
	for(i = 0; i<pos; i++)
		current = current->next;
	node = current->next;

	return node;
}



CircleListNode* CircleList_DeleteNode(CircleList *list, CircleListNode *node)
{
	TCircleList *tlist;
	int i;
	CircleListNode *current, *ret = NULL;
	if(NULL == list || NULL == node)
	{
		printf("CircleList_DeleteNode err (NULL == list || NULL == node)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;
	current = &tlist->header;
	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;
	CircleListNode *ret = NULL;
	if(NULL == list)
	{
		printf("CircleList_Reset err (NULL == list)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;
	tlist->slider = tlist->header.next;

	return  tlist->slider;
}
CircleListNode* CircleList_Current(CircleList *list)
{
	TCircleList *tlist;
	CircleListNode *ret = NULL;
	if(NULL == list)
	{
		printf("CircleList_Current err (NULL == list)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;

	return tlist->slider;
}
CircleListNode* CircleList_Next(CircleList *list)
{
	TCircleList *tlist;
	CircleListNode *ret = NULL;
	if(NULL == list)
	{
		printf("CircleList_Next err (NULL == list)\n");
		return NULL;
	}
	tlist = (TCircleList *)list;
	ret = tlist->slider;
	if(tlist->slider != NULL)
		tlist->slider = tlist->slider->next;

	return ret;
}

测试代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "CircleList.h"
typedef struct _Teacher
{
	CircleListNode node;
	int age;
	char name[64];
}Teacher;


typedef struct _Teacher2
{
	CircleListNode node;
	int age;
	char name[64];
}Teacher2;

typedef struct _Teacher3
{
	CircleListNode node;
	int age;
	char name[64];
	int age3;

}Teacher3;

//一般功能测试
void main12()
{
	int		ret = 0, i = 0;
	CircleList* list = NULL;

	Teacher t1, t2, t3, t4,t5;
	t1.age = 31;
	t2.age = 32;
	t3.age = 33;
	t4.age = 34;
	t5.age = 35;

	list = CircleList_Create();
	if (list == NULL)
	{
		printf("func CircleList_Create(10) ret :%d \n", ret);
		return ;
	}

	ret = CircleList_Insert(list, (CircleListNode*) &t1, 0); //头插法
	ret = CircleList_Insert(list, (CircleListNode*) &t2, 0); //头插法
	ret = CircleList_Insert(list, (CircleListNode*) &t3, 0); //头插法
	ret = CircleList_Insert(list, (CircleListNode*) &t4, 0); //头插法
	ret = CircleList_Insert(list, (CircleListNode*) &t5, 0); //头插法

	//遍历
	for (i=0; i<CircleList_Length(list); i++)
	{
		Teacher*  tmp = (Teacher *) CircleList_Get(list, i);
		if (tmp == NULL)
		{
			return ;
		}
		printf("tmp->age:%d ", tmp->age);
	}

	//删除链表中的节点
	while( CircleList_Length(list) > 0 )
	{
		CircleList_Delete(list, 0);
	}

	system("pause");


	return ;
}



struct Value
{
	CircleListNode header;
	int v;
};

//循环链表解决约瑟夫问题
void  main()
{
	int i = 0;
	CircleList* list = CircleList_Create();

	struct Value v1, v2, v3, v4, v5, v6, v7, 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, 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_Destory(list);

	system("pause");
	return ;
}

总结:

       循环链表比一般链表增加了循环的能力,但是还是没有解决链表逆向遍历耗时的缺点,

       所以循环链表的实用性并没有质的提升,但是对于接下来搞懂循环双向链表至关重要。





猜你喜欢

转载自blog.csdn.net/Blank2019/article/details/80718827