双向链表

意义:

如果算法中需要大量地找某指定结点的前趋结点,使用单链表无疑是灾难性的,因为单链表更适合 "从前往后" 找,而 "从后往前" 找并不是它的强项,在这个情况下使用双向链表

在双向链表中注意指针节点的移动,难度不大

TowWayLink.h

#pragma once
#include <stdlib.h>
#include <string.h>
#include <iostream>

// 玩家信息结构体
typedef struct PlayerInfo
{
	char chName[20]; // 名字
	int iRank; // 排名

	PlayerInfo * pPrior;
	PlayerInfo *pNext;

}STPlayerInfo;

class TowWayLink
{
public:
	TowWayLink();
	~TowWayLink();

	// 初始化链表
	STPlayerInfo*  InitLink(STPlayerInfo* pLink);

	// 创建节点
	STPlayerInfo* CreateNode(STPlayerInfo& stPlayerInfo);

	// 插入节点
	void InsertNode(STPlayerInfo* pLink,int iPos, STPlayerInfo& stPlayerInfo);

	// 后插法
	void InsertAfter(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo);

	// 删除指定元素
	void DelNode(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo);

	// 改变指定位置的指定元素
	bool ChangeNode(STPlayerInfo* pLink,int iPos, STPlayerInfo& stPlayerInfo);

	// 查询指定元素的位置
	STPlayerInfo * QueryNodeByNo(STPlayerInfo* pLink, int iPos,STPlayerInfo& stPlayerInfo);

	// 查询指定元素的节点地址
	STPlayerInfo * QueryNodePos(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo);

	// 输出、打印链表
	void PrintLink(STPlayerInfo* pLink);

	// 逆序打印
	void PrintLinkReverseOrder(STPlayerInfo* plink);

	// 测试方法
	void TestLink();
private:

};

TowWayLink.cpp

#include "TowWayLink.h"

TowWayLink::TowWayLink()
{
}

TowWayLink::~TowWayLink()
{
}

// 初始化链表
STPlayerInfo*  TowWayLink::InitLink(STPlayerInfo* pLink)
{
	pLink = (STPlayerInfo*)malloc(sizeof(STPlayerInfo));
	strcpy(pLink->chName, "#");

	pLink->pPrior = NULL;
	pLink->pNext = NULL;

	return pLink;
}

// 双向链表
STPlayerInfo* TowWayLink::CreateNode(STPlayerInfo& stPlayerInfo)
{
	STPlayerInfo *pNode = (STPlayerInfo*)malloc(sizeof(STPlayerInfo));

	pNode->pPrior = NULL;
	pNode->pNext = NULL;

	strcpy(pNode->chName,stPlayerInfo.chName);
	pNode->iRank = stPlayerInfo.iRank;

	return pNode;
}

// 插入链表
void TowWayLink::InsertNode(STPlayerInfo* pLink, int iPos, STPlayerInfo& stPlayerInfo)
{
	STPlayerInfo *pNode = CreateNode(stPlayerInfo); // 新节点

	if(1 == iPos) // 首元节点特殊考虑
	{
		pNode->pNext = pLink->pNext; // 新节点尾结点处理
		pNode->pPrior = pLink; // 新节点的头结点处理

		pLink->pNext = pNode; // 新节点前节点处理
		pLink->pNext->pPrior = pNode; // 新节点后节点处理
		return;
	}

	// 找到指定位置的节点
	for(int i = 1; i < iPos; i++)
	{
		if(NULL == pLink->pNext)
		{
			return;
		}

		pLink = pLink->pNext;
	}

	pNode->pNext = pLink->pNext; // 新节点尾结点处理
	pNode->pPrior = pLink; // 新节点的头结点处理

	pLink->pNext = pNode; // 新节点前节点处理
	pLink->pNext->pPrior = pNode; // 新节点后节点处理
}

// 后插法
void TowWayLink::InsertAfter(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo)
{
	STPlayerInfo *pNode = CreateNode(stPlayerInfo); // 新节点

	// 寻找尾结点
	while(pLink->pNext)
	{
		pLink = pLink->pNext;
	}

	pLink->pNext = pNode;
	pNode->pPrior = pLink;
}

// 删除指定元素
void TowWayLink::DelNode(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo)
{
	if(NULL == pLink)
	{
		return;
	}

	// 目标字符
	char chName[20];
	strcpy(chName, stPlayerInfo.chName);

	pLink = pLink->pNext;

	while(pLink)
	{
		if(0 == strcmp(chName, pLink->chName))
		{
			break;
		}
		pLink = pLink->pNext;
	}

	STPlayerInfo* pPreNode = pLink->pPrior;
	pPreNode->pNext = pLink->pNext;

	free(pLink);
	pLink = NULL;
}

// 修改节点
bool TowWayLink::ChangeNode(STPlayerInfo* pLink, int iPos, STPlayerInfo& stPlayerInfo)
{
	if( (iPos <=0)
		|| (NULL == pLink))
	{
		return false;
	}

	STPlayerInfo* pLinkCurr = QueryNodeByNo(pLink,iPos,stPlayerInfo);

	strcpy(pLinkCurr->chName, stPlayerInfo.chName);
	pLinkCurr->iRank = stPlayerInfo.iRank;

	return true;
}

// 查询节点
STPlayerInfo * TowWayLink::QueryNodeByNo(STPlayerInfo* pLink, int iPos, STPlayerInfo& stPlayerInfo)
{
	if( (NULL == pLink)
		||(iPos <=0) )
	{
		return NULL;
	}
	int iCount = 0;
	while(pLink->pNext)
	{
		iCount++;
		pLink = pLink->pNext;
		if(iCount == iPos)
		{
			return pLink;
		}
	}
	return NULL;
}

// 查询指定节点地址
STPlayerInfo * TowWayLink::QueryNodePos(STPlayerInfo* pLink, STPlayerInfo& stPlayerInfo)
{
	if(!pLink)
	{
		return NULL;
	}
	while(pLink->pNext)
	{
		pLink = pLink->pNext;
		if(0 == strcmp(pLink->chName,stPlayerInfo.chName))
		{
			return pLink;
		}
	}
	return NULL;
}

// 输出链表
void TowWayLink::PrintLink(STPlayerInfo* pLink)
{
	pLink = pLink->pNext;
	while(pLink)
	{
		char chName[20];
		int iRank;
		strcpy(chName,pLink->chName);
		iRank = pLink->iRank;

		std::cout <<"Name " << chName<<"  Rank "<<iRank<< std::endl;
		pLink = pLink->pNext;
	}
}

// 逆序输出链表
void TowWayLink::PrintLinkReverseOrder(STPlayerInfo* plink)
{
	if(NULL == plink)
	{
		return;
	}
	STPlayerInfo* pEndNode = NULL;
	while(plink->pNext)
	{
		plink = plink->pNext;
	}
	pEndNode = plink; // 尾节点
	while(pEndNode->pPrior)
	{
		if(0 == strcmp("#", pEndNode->chName))
		{
			return;
		}

		std::cout << "Name "<< pEndNode->chName <<"Rank "<< pEndNode->iRank << std::endl;
		pEndNode = pEndNode->pPrior;
	}
}

// 测试方法
void TowWayLink::TestLink()
{
	STPlayerInfo* pHead= NULL;
	STPlayerInfo* pLink = InitLink(pHead); // 初始化链表,活得链表头

	STPlayerInfo stApple;
	strcpy(stApple.chName,"Apple");
	stApple.iRank = 1;
	InsertAfter(pLink,stApple);

	STPlayerInfo stBanana;
	strcpy(stBanana.chName, "Banana");
	stBanana.iRank = 2;
	InsertAfter(pLink, stBanana);

	STPlayerInfo stMelon;
	strcpy(stMelon.chName, "Melon");
	stMelon.iRank = 3;
	InsertAfter(pLink, stMelon);

	STPlayerInfo stCoco;
	strcpy(stCoco.chName, "Coco");
	stCoco.iRank = 4;
	InsertAfter(pLink, stCoco);

	//PrintLink(pLink);
	
	// 删除指定元素
	//std::cout <<"删除指定元素" << std::endl;
	//DelNode(pLink, stMelon);
	//PrintLink(pLink);
	/*
	STPlayerInfo stOrange;
	strcpy(stOrange.chName, "Orange");
	stOrange.iRank = 21;
	InsertNode(pLink, 1, stOrange);

	STPlayerInfo stLemon;
	strcpy(stLemon.chName, "Lemon");
	stLemon.iRank = 23;
	InsertNode(pLink, 3, stLemon);
	*/
	// 添加指定地点的元素
	//std::cout << "添加之后" << std::endl;
	//PrintLink(pLink);

	// 修改节点
// 	STPlayerInfo stCoconut;
// 	strcpy(stCoconut.chName, "Coconut");
// 	stCoconut.iRank = 5;
// 	InsertNode(pLink, 5, stCoconut);
// 	ChangeNode(pLink,3, stCoconut);
// 	PrintLink(pLink);
	PrintLinkReverseOrder(pLink);
	
}

main.cpp

#include <iostream>
#include "TowWayLink.h"
using namespace std;

int main()
{
	TowWayLink mTowWayLink;

	mTowWayLink.TestLink();

	cin.get();
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值