意义:

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

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

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;
}