(头冷)数据结构学习日志三——对循环链表的操作(By Ivan小黄)

啊哈,老夫又来更博客啦!在这个千门万户曈曈日的中秋节假依然守在电脑屏幕前,掉发敲代码。今天嘞,我们来说说循环链表,所谓循环链表,就是首位相连的单链表,单链表的最后一个结点指向第一个结点。
虽然听起来高大上,但还是很简单的哈。好的鸭,我们来实现一下!

1.定义循环链表的数据和操作

在这个代码的基础上我们有一个定义DataElement的头文件,也很简单啦,就是上两篇定义的结构体DataType,包含id和姓名而已。
以下是定义的CirclularList(循环链表)的头文件

#pragma once
/**循环链表的定义
 *循环链表的特点:就是单链表的末尾元素的尾指针指向第一个节点
 *循环链表的优点:可以从链表的任意一个元素访问其他的元素
 */
#include"DataElement.h"
typedef struct CircularNode {
	DataType data;
	CircularNode * next;
}CircularNode;


/**循环链表的头结点*/
typedef struct CircularLinkList {
	CircularNode * next;
	int length;
};

/**	插入循环链表
 *参数1:要插入的循环链表
 *参数2:要插入的链表的位置
 *参数3:要插入链表的元素
 */
void InsertCircleList(CircularLinkList * cList, int pos, DataType elem);


/**	初始化循环链表
 *参数1:要初始化的循环链表
 *参数2:要赋给链表的数组元素
 *参数3:循环链表的长度
 */
void InitCircleList(CircularLinkList * cList, DataType * elems, int length);

/** 打印循环链表
 *参数1:需要打印的循环链表
 */
void PrintCircleList(CircularLinkList * cList);

/**删除循环链表元素(并返回删除的元素)
 *参数1:需要删除的循环链表
 *参数2:需要删除的元素的位置
 */
DataType DeleteCircularElem(CircularLinkList * cList, int pos);

2、实现头文件定义的操作

#include"CircleLinkList.h"
#include<stdlib.h>
#include<iostream>
using namespace std;
//	插入循环链表
void InsertCircleList(CircularLinkList * cList, int pos, DataType elem)
{

	//	建立一个新的循环链表结点
	CircularNode * cNode = new CircularNode;
	cNode->data = elem;
	cNode->next = NULL;

	if (pos == 1)	//	如果插入的位置为第一个元素的话
	{
		cNode->next = cList->next;
		if (!cNode->next)	//	如果循环链表没有元素时
		{
			cNode->next = cNode;	//	指向cNode,构成一个元素的循环链表
		}
		else    //	如果循环链表中有元素的话,先找到最后一个元素
		{
			CircularNode * lastNode = new CircularNode;
			lastNode = cList->next;    
			for (int i = 1; i < cList->length; i++)
			{
				lastNode = lastNode->next;
			}
			//	最后一个元素的指针域指向第一个结点
			lastNode->next = cNode;	
		}
		cList->next = cNode;
		cList->length++;
	}

	else
	{
		CircularNode * currNode = new CircularNode;
		currNode = cList->next;
		for (int i = 1; currNode && i < pos - 1; i++)
		{
			currNode = currNode->next;
		}
		if (currNode)
		{
			cNode->next = currNode->next;
			currNode->next = cNode;
			cList->length++;
			if (pos == cList->length)
			{
				cNode->next = cList->next;
			}
			
		}
	}
}

//	初始化循环链表
void InitCircleList(CircularLinkList * cList, DataType * elems, int length)
{	
	CircularNode * node = new CircularNode;
	
	if (!cList->next)	//	如果循环链表为空
	{
		cList->length = 0;
	}
	for (int i = 0; i < length; i++)
	{
		InsertCircleList(cList, i + 1, elems[i]);
	}
}

void PrintCircleList(CircularLinkList * cList)
{
	CircularNode * node = new CircularNode;
	node = cList->next;
	for (int i = 0; i < cList->length; i++)
	{
		cout << node->data.id << "\t" << node->data.name << endl;
		node = node->next;
	}
}

/**删除循环链表元素(并返回删除的元素)
 *参数1:需要删除的循环链表
 *参数2:需要删除的元素的位置
 */
DataType DeleteCircularElem(CircularLinkList * cList, int pos)
{
	CircularNode * node = new CircularNode;
	DataType element;
	element.id = -9999;
	node = cList->next;
	if (pos == 1)	//	如果删除的是循环链表的第一个元素
	{	
		if (node) {
			element = node->data;
			CircularNode * lastNode = new CircularNode;
			lastNode = cList->next;
			for (int i = 1; i < cList->length; i++)
			{
				lastNode = lastNode->next;
			}
			cList->next = node->next;
			lastNode->next = node->next;
			delete node;
			cList->length--;
		}
	}

	else
	{
		CircularNode * preNode = NULL;
		for (int i = 1; node && i < pos; i++)
		{
			preNode = node;
			node = node->next;
		}
		element = node->data;
		preNode->next = node->next;
		delete node;
		cList->length--;
	}
	return element;
}

3.最后的测试程序

#include"CircleLinkList.h"
#include<iostream>
using namespace std;
void TestCircularList();

DataType dataElements[5] = {
	{1, "小明"},
	{2, "小丽"},
	{3, "小猪"},
	{4, "小狗"},
	{5, "小猫"}
};

int main()
{
	TestCircularList();
	return 0;
}

void TestCircularList()
{
	CircularLinkList * cList = new CircularLinkList;
	cList->length = 0;
	cList->next = NULL;
	InitCircleList(cList, dataElements, 5);
	PrintCircleList(cList);
	DataType insData = {9, "小象"};
	InsertCircleList(cList, 6, insData);
	PrintCircleList(cList);
	DeleteCircularElem(cList, 3);
	PrintCircleList(cList);
}

好啦,因为这个循环链表的算法跟单链表很相似,所以我不想写太多,没有必要嘛。重点是理解二者之间的区别,然后小改一下。感觉学数据结构还是跟修炼内功一样,慢慢来,水滴石穿。加油加油鸭嚯嚯嚯!!!(虚伪的加油打气)

猜你喜欢

转载自blog.csdn.net/qq_19927141/article/details/82818987