啊哈,老夫又来更博客啦!在这个千门万户曈曈日的中秋节假依然守在电脑屏幕前,掉发敲代码。今天嘞,我们来说说循环链表,所谓循环链表,就是首位相连的单链表,单链表的最后一个结点指向第一个结点。
虽然听起来高大上,但还是很简单的哈。好的鸭,我们来实现一下!
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);
}
好啦,因为这个循环链表的算法跟单链表很相似,所以我不想写太多,没有必要嘛。重点是理解二者之间的区别,然后小改一下。感觉学数据结构还是跟修炼内功一样,慢慢来,水滴石穿。加油加油鸭嚯嚯嚯!!!(虚伪的加油打气)