双向循环链表 DoubleLoopLinkedList

一、双向循环链表的基本概念:

        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

五、应用:

       在遇到要求进行双向一定的问题时,都可以考虑使用双向链表。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值