一、双向循环链表的基本概念:
1、前驱节点:当前节点的前一节点,即左链域(LLink)指向的节点。
2、后继节点:当前节点的后一节点,即右链域(RLink)指向的节点。
二、双向循环链表的节点的基本构成:
1、左链域(LLink):链接上一个节点右链域,通过左链域可以向链表的前面查找。
2、数据域(data):存放节点的数据
2、右链域(RLink):链接下一个节点的左链域,通过右链域可以向链表的后面查找。
typedef int DLLLDATA;
typedef struct node DLLLNODE;
typedef struct node
{
DLLLNODE * LLink; //左链域
DLLLDATA data; //数据域
DLLLNODE * RLink; //右链域
};
三、双向循环链表的特点:
1、可以双向移动。
2、首尾互联,即头节点的左链域指向尾节点,尾节点的右链域指向头节点。
四、双向循环链表的基本操作及代码实现:
表头(head),即数据域为空的节点,带表头的链表可以使操作的实现更方便!
1、创建一个空表
//DLLLCreate.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLCreate()//创建一个空的双向循环链表
{
DLLLNODE * head = (DLLLNODE *)calloc(1, sizeof(DLLLNODE));
head->LLink = NULL;
head->data = 0;
head->RLink = NULL;
return head;
}
2、向一个表中插入一个数
//DLLLInsertion.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLInsertion(DLLLNODE * head, DLLLDATA data)//向DLLL中插入一个新的节点
{
DLLLNODE * newNode = (DLLLNODE *)calloc(1, sizeof(DLLLNODE));
newNode->data = data;
if (NULL == head->LLink) //空表
{
newNode->LLink = head;
newNode->RLink = head;
head->LLink = newNode;
head->RLink = newNode;
}
else //非空表
{
newNode->RLink = head;
newNode->LLink = head->LLink;
head->LLink->RLink = newNode;
head->LLink = newNode;
}
return head;
}
3、删除表中的某一个数
//DLLLDelete.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLDelete(DLLLNODE * head, DLLLDATA deData)//删除
{
DLLLNODE * temp = head->RLink;
cout<<"要删除的数为:"<<deData<<endl;
while ( 0 != temp->RLink->data)//未到表尾
{
if (deData == temp->data)//找到了要删除的节点
{
temp->LLink->RLink = temp->RLink;
temp->RLink->LLink = temp->LLink;
free(temp);
return head;
}
temp = temp->RLink;
}
return NULL;
}
4、查找表中的某个数
//DLLLSearch.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLSearch(DLLLNODE * head, DLLLDATA schData)//查找
{
DLLLNODE * temp = head->RLink;
while (temp->RLink->data != 0)//未到尾节点
{
if (temp->data == schData)//找到要找的节点
{
return temp;
}
temp = temp->RLink;
}
cout<<"该链表中没有要找的数据: "<<schData<<endl;
return NULL;
}
5、获取前驱节点
//DLLLGetPreNode.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLGetPreNode(DLLLNODE * head, DLLLDATA target)//获得target的前驱节点
{
DLLLNODE * temp = DLLLSearch(head, target);
if (temp != NULL)
{
return (temp->LLink);
}
return NULL;
}
6、获取后继节点
//DLLLGetPosNode.cpp
#include "DoubleLoopLinkedList.h"
DLLLNODE * DLLLGetPosNode(DLLLNODE * head, DLLLDATA target)//获取target的后继节点
{
DLLLNODE * temp = DLLLSearch(head, target);
if (temp != NULL)
{
return (temp->RLink);
}
return NULL;
}
7、输出表
//DLLLShow.cpp
#include "DoubleLoopLinkedList.h"
void DLLLShow(DLLLNODE * head)//显示
{
DLLLNODE * temp = head->RLink;
while (temp->data != 0)
{
cout<<temp->data<<"->";
temp = temp->RLink;
}
cout<<"NULL"<<endl;
}
主函数
//main.cpp
#include "DoubleLoopLinkedList.h"
#define N 10
int data[N] = {2, 3, 4, 1, 9, 5, 8, 7, 6, 10};
int main()
{
int i;
int deData = 1; //要删除的数据
int schData = 16;//要查找的数据
int tarData = 8; //找其前驱和后继
DLLLNODE * head = DLLLCreate();
DLLLNODE * temp;
for (i = 0; i < N; i++)
{
DLLLInsertion(head, data[i]);
}
cout<<"当前链表的原始数据:";
DLLLShow(head);
DLLLDelete(head,deData);
cout<<"删除之后的原始数据:";
DLLLShow(head);
temp = DLLLSearch(head, schData);
if (temp)
{
cout<<"要找的数是:"<<temp->data<<endl;
}
temp = DLLLGetPreNode(head,tarData);
if (temp)
{
cout<<"要找的节点:"<<tarData<<" 的前驱节点为:"<<temp->data<<endl;
}
temp = DLLLGetPosNode(head,tarData);
if (temp)
{
cout<<"要找的节点:"<<tarData<<" 的后继节点为:"<<temp->data<<endl;
}
return 0;
}
头文件
//DoubleLoopLinkedList.h
#ifndef __DOUBLELOOPLINKEDLIST_H
#define __DOUBLELOOPLINKEDLIST_H
/************************************************************************/
#include <iostream>
using namespace std;
/************************************************************************/
typedef int DLLLDATA;
typedef struct Node DLLLNODE;
struct Node
{
DLLLNODE * LLink; //左链域
DLLLDATA data; //数据域
DLLLNODE * RLink; //右链域
};
/************************************************************************/
DLLLNODE * DLLLCreate();//创建一个空的双向循环链表
DLLLNODE * DLLLInsertion(DLLLNODE * head, DLLLDATA data); //向DLLL中插入一个新的节点
DLLLNODE * DLLLDelete(DLLLNODE * head, DLLLDATA deData); //删除
DLLLNODE * DLLLSearch(DLLLNODE * head, DLLLDATA schData); //查找
DLLLNODE * DLLLGetPreNode(DLLLNODE * head, DLLLDATA target);//获得target的前驱节点
DLLLNODE * DLLLGetPosNode(DLLLNODE * head, DLLLDATA target);//获取target的后继节点
void DLLLShow(DLLLNODE * head);//显示
/************************************************************************/
#endif
五、应用:
在遇到要求进行双向一定的问题时,都可以考虑使用双向链表。