单向循环链表的定义与实现

单向循环链表

说明1:以下代码在VS2017中编译通过,读者使用时可以直接将头文件(CLinkList.h),源文件(CLinkList.c),主文件(main.c)中的内容直接拷贝过去,即可编译运行!

说明2:图示在这里插入图片描述

头文件:CLinkList.h(函数的声明)

#ifndef  _CLINKLIST_H_
#define _CLINKLIST_H_
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <stdbool.h>

#define ElemType int 
typedef struct ListNode
{
	ElemType data;
	struct ListNode* next;				
}ListNode,*pListNode;

typedef struct LinkList
{
	pListNode head;
	pListNode tail;
	size_t size;
}LinkList;

/
void InitList(LinkList* list);
ListNode* CreateNode(ElemType data);
void push_back(LinkList* list, ElemType data);
void push_front(LinkList* list, ElemType data);
void ShowList(LinkList* list);
void pop_back(LinkList* list);
void pop_front(LinkList* list);
bool Empty(LinkList* list);
void Insert_By_Value(LinkList* list, ElemType data);
pListNode Find_data(LinkList* list, ElemType Key);
int Length(LinkList* list);
void Delete_By_Value(LinkList* list, ElemType Key);
void Delete_By_Value_Traditaonal(LinkList* list, ElemType Key);
void Sort(LinkList* list);
void Reverse(LinkList* list);	//数据反转
void Clear(LinkList* list);
void Destory(LinkList* list);
pListNode Find(LinkList* list, ElemType Key);
pListNode Prior(LinkList* list, ElemType PosData);		//求PosData结点的前驱
pListNode Next(LinkList* list, ElemType PosData);		//求PosData结点的后继


#endif // ! _CLINKLIST_H_

源文件:CLinkList.c(函数的定义)

#include "CLinkList.h"

void InitList(LinkList* list)
{
	list->head = list->tail = (pListNode)malloc(sizeof(ListNode));
	assert(list->head != NULL);
	list->tail->next = list->head;
	list->size = 0;
}

ListNode * CreateNode(ElemType data)
{
	ListNode* NewNode = (pListNode)malloc(sizeof(ListNode));
	assert(NewNode != NULL);
	NewNode->data = data;
	NewNode->next = NULL;
	return NewNode;
}

void push_back(LinkList* list, ElemType data)
{
	pListNode NewNode = CreateNode(data);
	list->tail->next = NewNode;
	list->tail = NewNode;
	list->tail->next = list->head;
	list->size++;
}

void push_front(LinkList* list, ElemType data)
{
	pListNode NewNode = CreateNode(data);
	NewNode->next = list->head->next;
	list->head->next = NewNode;
	if (list->size == 0)
		list->tail = NewNode;
	list->size++;
}

void ShowList(LinkList* list)
{
	pListNode pMove = list->head->next;
	while (pMove != list->head)
	{
		printf("%d--->", pMove->data);
		pMove = pMove->next;
	}
	printf(".Nul\n");
}

void pop_back(LinkList* list)
{
	if (list->size == 0)
		return;
	pListNode pMove = list->head;
	while (pMove->next != list->tail)
	{
		pMove = pMove->next;
	}
	free(list->tail);
	list->tail = pMove;
	list->tail->next = list->head;
	list->size--;
}

void pop_front(LinkList* list)
{
	if (list->size == 0)
		return;
	pListNode pMove = list->head->next;
	list->head->next = pMove->next;
	free(pMove);
	if (list->size == 1)
		list->tail = list->head;
	list->size--;
}

bool Empty(LinkList* list)
{
	return list->size == 0;
}

void Insert_By_Value(LinkList* list, ElemType data)
{
	pListNode pMove = list->head;
	while (pMove->next != list->tail && pMove->next->data < data)
	{
		pMove = pMove->next;
	}
	if (pMove->next == list->tail && pMove->next->data < data)	//最后面插入
	{
		push_back(list, data);
	}
	else
	{
		pListNode NewNode = CreateNode(data);
		NewNode->next = pMove->next;
		pMove->next = NewNode;
		list->size++;
	}
}

pListNode Find_data(LinkList* list, ElemType Key)
{
	if (list->size == 0)
		return NULL;
	pListNode pMove = list->head->next;
	while (pMove != list->head && pMove->data != Key)
	{
		pMove = pMove->next;
	}
	if (pMove == list->head)
		return NULL;
	return pMove;
}

int Length(LinkList* list)
{
	return list->size;
}

void Delete_By_Value(LinkList* list, ElemType Key)
{
	if (list->size == 0)
		return;
	pListNode pFind = Find_data(list, Key);
	if (pFind == NULL)
	{
		printf("查无此数,无法删除!\n");
		return;
	}
	if (pFind == list->tail)
	{
		pop_back(list);
	}
	else if (pFind->next == list->tail)		//倒数第二个结点(必须单独考虑,list->tail指向要发生改变)
	{
		pListNode q = pFind->next;
		pFind->data = q->data;
		pFind->next = q->next;
		list->tail = pFind;
		free(q);
		q = NULL;
		list->size--;
	}
	else
	{
		pListNode q = pFind->next;
		pFind->data = q->data;
		pFind->next = q->next;
		if (pFind->next == list->tail)
			list->tail = pFind;
		free(q);
		q = NULL;
		list->size--;
	}
}

void Delete_By_Value_Traditaonal(LinkList* list, ElemType Key)
{
	if (list->size == 0)
		return;
	pListNode pFind = Find_data(list, Key);
	if (pFind == NULL)
	{
		printf("查无此数,无法删除!\n");
		return;
	}
	if (pFind == list->head->next)	//删除的是第一个结点
		pop_front(list);
	else if (pFind == list->tail)	//删除的是最后一个结点
		pop_back(list);
	else
	{
		pListNode pPrior = Prior(list, pFind->data);
		pPrior->next = pFind->next;
		free(pFind);
		pFind = NULL;
		list->size--;
	}
}

void Sort(LinkList* list)
{
	if (list->size == 0 || list->size == 1)
		return;
	//首先分割
	pListNode pMove1 = list->head->next;
	pListNode pMove2 = pMove1->next;
	list->tail->next = NULL;
	list->tail = pMove1;
	list->tail->next = list->head;
	//然后进行插入及其连接
	while (pMove2 != NULL)
	{
		pMove1 = pMove2;
		pMove2 = pMove2->next;

		pListNode pMove = list->head;
		while (pMove->next != list->tail && pMove->next->data < pMove1->data)
		{
			pMove = pMove->next;
		}
		if (pMove->next == list->tail && pMove->next->data < pMove1->data)
		{
			pMove1->next = list->tail->next;
			list->tail->next = pMove1;
			list->tail = pMove1;
		}
		else
		{
			pMove1->next = pMove->next;
			pMove->next = pMove1;
		}
	}
}

void Reverse(LinkList* list)
{
	if (list->size == 0 || list->size == 1)
		return;
	pListNode pMove1 = list->head->next;
	pListNode pMove2 = pMove1->next;
	list->tail->next = NULL;
	list->tail = pMove1;
	list->tail->next = list->head;
	while (pMove2 != NULL)
	{
		pMove1 = pMove2;
		pMove2 = pMove2->next;
		pMove1->next = list->head->next;
		list->head->next = pMove1;
	}
}

void Clear(LinkList* list)
{
	if (list->size == 0)
		return;
	pListNode pMove = list->head->next;
	while (pMove != list->head)
	{
		list->head->next = pMove->next;
		free(pMove);
		pMove = list->head->next;
	}
	list->tail = list->head;
	list->size = 0;
}

void Destory(LinkList* list)
{
	Clear(list);
	free(list->head);
	list->head = list->tail = NULL;
}

pListNode Find(LinkList* list, ElemType Key)
{
	ListNode* pFind = Find_data(list, Key);
	if (pFind == NULL || list->size == 0 || list->size == 1 || list->head->next->data == Key)
		return NULL;
	pListNode pMove = list->head->next;
	while (pMove->next != list->head && pMove->next->data != Key)
	{
		pMove = pMove->next;
	}
	return pMove;
}

pListNode Prior(LinkList* list, ElemType PosData)
{
	return Find(list,PosData);
}

pListNode Next(LinkList* list, ElemType PosData)
{
	ListNode* pFind = Find_data(list, PosData);
	if (pFind == NULL)
		return NULL;
	if (pFind->next == list->head)
		return NULL;
	return pFind->next;
}

主文件:main.c(测试文件)

#include "CLinkList.h"

int main()
{
	LinkList MyLinkList;
	InitList(&MyLinkList);
	push_back(&MyLinkList, 3);
	push_back(&MyLinkList, 1);
	push_back(&MyLinkList, 10);
	push_back(&MyLinkList, 7);
	ShowList(&MyLinkList);
	//push_front(&MyLinkList, 6);
	//push_front(&MyLinkList, 7);
	//push_front(&MyLinkList, 8);
	//ShowList(&MyLinkList);
	//pop_back(&MyLinkList);
	//pop_front(&MyLinkList);
	//ShowList(&MyLinkList);
	Insert_By_Value(&MyLinkList, 0);
	ShowList(&MyLinkList);
	//pListNode pFind = Find_data(&MyLinkList, 7);
	//Delete_By_Value(&MyLinkList, 7);
	//Delete_By_Value(&MyLinkList, 0);
	//Delete_By_Value(&MyLinkList, 3);
	ShowList(&MyLinkList);
	Sort(&MyLinkList);
	ShowList(&MyLinkList);
	Reverse(&MyLinkList);
	ShowList(&MyLinkList);
	//Clear(&MyLinkList);
	pListNode  pNext = Next(&MyLinkList, 10);//7
	pNext = Next(&MyLinkList, 3);//1
	pNext = Next(&MyLinkList, 0);//NULL

	pListNode pPrior = Prior(&MyLinkList, 10);//NULL
	pPrior = Prior(&MyLinkList, 3);//7
	pPrior = Prior(&MyLinkList, 0);//1
	Delete_By_Value_Traditaonal(&MyLinkList, 10);
	Delete_By_Value_Traditaonal(&MyLinkList, 3);
	Delete_By_Value_Traditaonal(&MyLinkList, 0);
	ShowList(&MyLinkList);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@十三阿哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值