双向链表总结

基本数据结构之-双向链表

双向链表和单向链表明显的区别就是,双向链表可以向前查找,也就是能直接找到它自己的前驱结点,但是双向链表不是循环链表!

分析基本的数据结构,每个结点都有自己的数据域和两个指针域,一个指向前驱,一个指向后继,但是为了通用性,我们只考虑一个前驱和一个后继的关系

typedef struct _DOUBLE_LIST_NODE

{

// 定义双向链表的前驱和后继

struct _DOUBLE_LIST_NODE *Pre;

struct _DOUBLE_LIST_NODE  *Next;

}DoubleListNode, *DoubleSidedList;

// 初始化

int Init_DoubleSidedList(DoubleSidedList *doublesidedlist)

{

if (doublesidedlist == NULL)

{

exit(-1);

}

if (*doublesidedlist == NULL)

{

*doublesidedlist = (DoubleSidedList)malloc(sizeof(DoubleListNode));

}

(*doublesidedlist)->Next = NULL;

(*doublesidedlist)->Pre = NULL;

return 0;

}

// 销毁,不要释放其他位置的空间,不知道是栈内存还是堆内存,并且不知道是什么数据类型

void Destroy_DoubleSidedList(DoubleSidedList doublesidedlist)

{

if (doublesidedlist == NULL)

{

return;

}

free(doublesidedlist);

}

// 仅仅是把指针置空

void Clear_DoubleSidedList(DoubleSidedList doublesidedlist)

{

if (doublesidedlist == NULL)

{

return;

}

doublesidedlist->Next = NULL;

doublesidedlist->Pre = NULL;

}

int Empty_DoubleSidedList(DoubleSidedList doublesidedlist)

{

if (doublesidedlist==NULL)

{

return -1;

}

// 如果next为空,肯定链表也是空的

return doublesidedlist->Next == NULL;

//

}

// 返回当前双向链表的长度

int Length_DoubleSidedList(DoubleSidedList doublesidedlist)

{

if (doublesidedlist == NULL)

{

return 0;

}

int length = 0;

// 第一个元素的开始的位置在 定义Next开始

DoubleListNode *pCurrent =doublesidedlist->Next;

while (pCurrent!= NULL)

{

++length;

pCurrent = pCurrent->Next;

}

return length;

}

void * GetElem_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos)

{

if (doublesidedlist == NULL)

{

return NULL;

}

if (Pos<0 || Pos>Length_DoubleSidedList(doublesidedlist)-1)

{

return NULL;

}

DoubleListNode *pCurrent = doublesidedlist->Next;

int i = 0;

while (i<Pos)

{

pCurrent = pCurrent->Next;

++i;

}

// 返回所在的位置 从 0 开始

return pCurrent;

}

// 查看链表中是否存在某个值,返回所在的位置

int  LocateElem_DoubleSidedList(DoubleSidedList doublesidedlist, void* data, int(*compare)(void *data1, void *data2))

{

if (doublesidedlist==NULL)

{

return -1;

}

if (data == NULL)

{

return -2;

}

if (compare == NULL)

{

return -4;

}

DoubleListNode *Node = (DoubleListNode *)data;

int i = 0;

DoubleListNode *pCurrent = doublesidedlist->Next;

while (pCurrent!= NULL)

{

// 必须要传入比较函数

if (compare(pCurrent, Node))

{

return i;

}

pCurrent = pCurrent->Next;

++i;

}

return -3;

}

// 返回前驱,这儿就可以体现出双向链表的优势

void *PriorElem_DoubleSidedList(DoubleSidedList doublesidedlist, void *data)

{

if (doublesidedlist == NULL)

{

return NULL;

}

if (data == NULL)

{

return NULL;

}

DoubleListNode *pCurrent = doublesidedlist->Next;

while (pCurrent != NULL)

{

#if 0

if (pCurrent->Next==data)

{

return pCurrent;

}

#else

if (pCurrent == data)

{

//这就是双向链表的好处

return pCurrent->Pre;

}

#endif

pCurrent = pCurrent->Next;

}

return NULL;

}

// 返回后继

void* NextElem_DoubleSidedList(DoubleSidedList doublesidedlist, void *data)

{

if (doublesidedlist == NULL)

{

return NULL;

}

if (data == NULL)

{

return NULL;

}

DoubleListNode *pCurrent = doublesidedlist;

while (pCurrent->Next != NULL)

{

if (pCurrent == data)

{

return pCurrent->Next;

}

pCurrent = pCurrent->Next;

}

return NULL;

}

// 插入操作,一定要考虑特殊的情况

int Insert_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos, void * data)

{

if (doublesidedlist == NULL)

{

return -1;

}

if (data == NULL)

{

return -2;

}

if (Pos < 0)

{

Pos = 0;

}

if (Pos > Length_DoubleSidedList(doublesidedlist))

{

Pos = Length_DoubleSidedList(doublesidedlist);

}

DoubleListNode *pCurrent = doublesidedlist;

for (int i = 0; i < Pos; ++i)

{

pCurrent = pCurrent->Next;

}

DoubleListNode *Node = (DoubleListNode *)data;

//

if (Pos==0 && Length_DoubleSidedList(doublesidedlist) == 0)

{

// 最前面一个位置插入 && 当前长度为0 插入的结点不存在后继结点

Node->Next = pCurrent->Next;

Node->Pre = pCurrent;

pCurrent->Next = Node;

}

else if (Length_DoubleSidedList(doublesidedlist) == Pos)

{

// 最后一个结点不存在后继结点

Node->Next = pCurrent->Next;

Node->Pre = pCurrent;

pCurrent->Next = Node;

}

else

{

Node->Next = pCurrent->Next;

pCurrent->Next->Pre = Node;

pCurrent->Next = Node;

Node->Pre = pCurrent;

}

return 0;

}

// 删除操作 一定要考虑特殊的情况

int  DeleteByPos_DoubleSidedList(DoubleSidedList doublesidedlist, int Pos)

{

if (doublesidedlist == NULL)

{

return -1;

}

if (Pos<0 || Pos>Length_DoubleSidedList(doublesidedlist) - 1)

{

return -2;

}

DoubleListNode *pCurrent = doublesidedlist->Next;

// 找到前驱

for (int i = 0; i < Pos; ++i)

{

pCurrent = pCurrent->Next;

}

// 如果删除的是最后一个结点,那么找不到最后一个结点的下一个结点

if (Pos == Length_DoubleSidedList(doublesidedlist))

{

pCurrent->Pre->Next = NULL;

}

else

{

pCurrent->Next->Pre = pCurrent;

pCurrent->Next = pCurrent->Next->Next;

}

return 0;

}

int  DeleteByVal_DoubleSidedList(DoubleSidedList doublesidedlist, void* data)

{

if (doublesidedlist == NULL)

{

return -1;

}

DoubleListNode *pCurrent = doublesidedlist->Next;

while (pCurrent->Next != NULL )

{

if (pCurrent == data)

{

break;

}

pCurrent = pCurrent->Next;

}

// 如果是最后一个结点,

if (pCurrent->Next == NULL)

{

pCurrent->Pre->Next = NULL;

}

else

{

pCurrent->Next->Pre = pCurrent;

pCurrent->Next = pCurrent->Next->Next;

}

return 0;

}

// 遍历操作

void Traverse_DoubleSidedList(DoubleSidedList doublesidedlist, void(*Traverse)(void *data))

{

if (doublesidedlist == NULL)

{

return;

}

if (Traverse == NULL)

{

return;

}

DoubleListNode *pCurrent = doublesidedlist->Next;

while (pCurrent != NULL)

{

Traverse(pCurrent);

pCurrent = pCurrent->Next;

}

}

时间: 2024-10-21 00:57:56

双向链表总结的相关文章

数据结构第四篇——线性表的链式存储之双向链表

?注:未经博主同意,不得转载. 前面讨论的单链表,每个结点中只有一个指针域,用来存放指向后继结点的指针,因此,从某个结点出发只能顺时针往后查找其他结点.若要查找某个结点的直接前驱,则需要从头指针开始沿链表探寻,处理起来十分不方便.为克服单链表的这一缺点,可引入双向链表. 双向链表中每一个结点含有两个指针域,一个指针指向其直接前驱结点,另一个指针指向直接后继结点.和单链表类似,双向链表一般也只有头指针唯一确定:同样也可设头结点,使得双向链表的某些操作简便一些. 双向链表结构定义如下:  双向链表是

双向链表(一)

参考: http://blog.sina.com.cn/s/blog_7d44748b01013fsf.html    (写的太好啦) http://blog.163.com/haibianfeng_yr/blog/static/34572620201453061036702/ 双(向)链表中有两条方向不同的链,即每个结点中除next域存放后继结点地址外,还增加一个指向其直接前趋的指针域prior.双向链表在查找时更方便 特别是大量数据的遍历 注意:    ①双链表由头指针head惟一确定的. 

c语言双向链表

typedef int ElemType; typedef struct _Node { ElemType value; struct _Node* pnext; struct _Node* prev; }node, *pNode; //创建双向链表 pNode Create_Double_List(int count) { pNode pn = NULL; pNode pb = NULL; pNode phead = (pNode)malloc(sizeof(node)); printf("请

C++__双向链表(练习)

双向链表 link.h #ifndef LINK_H_ #define LINK_H_ #define HEADER 0 #define TAIL -1 typedef int data_type; enum LINK_OP { LINK_ERR = -1, LINK_OK }; class LINK { private: data_type data; LINK *next; LINK *last; public: LINK(); LINK(data_type data); virtual ~

剑指offer:二叉搜索树与双向链表

1.题目描述: 输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表.要求不能创建任何新的结点,只能调整树中结点指针的指向. 2.解题思路: (1)将左子树构造成双向链表,并返回链表头节点: (2)定位左子树双链表的尾节点: (3)如果左子树链表不为空,将当前root连缀其链尾: (4)将右子树构造出双向链表,并返回链表头节点: (5)如果右子树链表不为空,将当前root连缀其表头: (6)根据左子树链表是否为空,确定返回的节点. 3.JavaScript实现: function Conv

Uva 12657 Boxes in a Line 双向链表

操作4比较特殊,为了避免一次性修改所有元素的指针,由于题目只要求输出奇数盒子的编号,所以我们可以灵活的根据是否进行过操作4对操作1 操作2 进行改动 操作3不受操作4影响 上代码.... #include<cstdio> #include<algorithm> const int maxn=100000+5; int right[maxn],left[maxn]; void link (int L,int R){ right[L]=R;left[R]=L; } //在双向链表这样复

双向链表 Boxes in a Line UVA - 12657

首先记录一下对链表的理解,最初看链表是在教材上看的,上面是用结构体, 理解起来还不是很困难,我也以为自己懂了,然而看到紫书上链表用的是数组(UVA11988),真的是..到最后把他的代码背下来了都还是有点晕(/(ㄒoㄒ)/~~),那个时候做题有点匆忙,也就没深究,不过后面那道(也就是这道)也就没再写了,差不多隔了一个月吧,有那么一点点感觉就是这次没看代码自己写过一遍后. 单向每一个结构体有两个元素(或者更多),其中一个是下一个元素的地址,其他的是他本身有的东西,在这道题中,1 2 3 4 5,

Shuffling Machine和双向链表

1. 双向链表 https://github.com/BodhiXing/Data_Structure 2. Shuffling Machine https://pta.patest.cn/pta/test/17/exam/4/question/264 思路: 代码: 1 #include <iostream> 2 using namespace std; 3 4 #define MAXCARD 54 5 6 string int2str(int x) 7 { 8 char ch[4]; 9

二叉搜索树与双向链表

void convertNode(BSTreeNode *root, BSTreeNode ** pLastNodeInList) { if(!root) return ; if(root->left) { convertNode(root->left, pLastNodeInList); } root->left = *pLastNodeInList; if(*pLastNodeInList != NULL) (*pLastNodeInList)->right = root; *

数据结构 线性双向链表

//线性双向链表 #ifndef _MY_DLINKLIST_H_ #define _MY_DLINKLIST_H_ typedef void DLinkList; typedef struct _tag_DLinkListNode { struct _tag_DLinkListNode* next; struct _tag_DLinkListNode * pre; }DLinkListNode; //创建双向链表 DLinkList* DLinkList_Create(); //销毁双向链表