一、概念
双向链表:是在单链表的每个结点中,在设置一个指向其前驱结点的指针域
可回退
二、代码实现
1、存储结构
typedef int ElemType;
typedef struct Node
{
ElemType data;
struct Node* prev;//前驱
struct Node* next;//后继
}Node,*DPList;//本身类型为结点类型,指针类型为DPList
2、初始化
void init(DPList plist)
{
if (plist == nullptr)
{
exit(0);
}
plist->prev = nullptr;
plist->next = nullptr;
}
3、插入
- 购买结点(插入一个结点的前提是先有一个结点)
Node* buyNode(ElemType val)
{
Node* pnewnode = (Node*)malloc(sizeof(Node));
pnewnode->data = val;
pnewnode->prev = nullptr;
pnewnode->next = nullptr;
return pnewnode;
}
(1)头插
(要操作main函数中的phead,需将insertHead中的phead解一次引用(*phead),
*phead操作main函数中的phead
//插入考虑插入第一个元素
int insertHead(DPList plist, ElemType val)//定义一个指针类型将结构拿到
{
Node* pnewnode = buyNode(val);
pnewnode->next = plist->next;
pnewnode->prev = plist;
if (plist->next != nullptr)//说明有数据结点(必须进行判断,因为null不能取前指针域
{
plist->next->prev = pnewnode;
}
plist->next = pnewnode;
return 1;
}
(2)尾插
int insertTail(DPList plist, ElemType val)
{
Node* pnewnode = buyNode(val);
Node* pTail = plist;
while (pTail->next != nullptr)
{
pTail = pTail->next;
}
pTail->next = pnewnode;
pnewnode->prev = pTail;
return 1;
}
(3)按位置插入
获取当前链表长度
int getLength(DPList plist)
{
int count = 0;
Node* pCur = plist->next;//从第一个数据结点开始判断
while (pCur != nullptr)
{
count++;
pCur = pCur->next;
}
return count;
}
int insertPos(DPList plist, int pos, ElemType val)
{
Node* pfront = plist;
int i = 0;
if (pos < 0 || pos > getLength(plist))
{
return 0;
}
for (i; i < pos; i++)
{
pfront = pfront->next;
}
Node* pnewnode = buyNode(val);
pnewnode->next = pfront->next;
pnewnode->prev = pfront;
pfront->next->prev = pnewnode;
pfront->next = pnewnode;
return 1;
}
4、删除
判空(删除一个结点首先先判断结点是否存在)
int empty(DPList plist)
{
return plist->next == nullptr ? 1 : 0;
}
(1)头删
//删除考虑尾部元素的删除
int deleteHead(DPList plist)
{
Node* pCur = plist->next;
plist->next = pCur->next;
if (pCur->next != nullptr)
{
pCur->next->prev = plist;
}
free(pCur);
return 1;
}
(2)尾删
int deleteTail(DPList plist)
{
if (empty(plist))
{
return 0;
}
Node* ptail2 = plist;
Node* pCur = nullptr;
while (ptail2->next != nullptr)//判断指针指向的下一个结点是否为空
{
if (ptail2->next->next == nullptr)
{
break;
}
ptail2 = ptail2->next;
}
pCur = ptail2->next;
ptail2->next = nullptr;
free(pCur);
return 1;
}
(3)按位置删除
int deletePos(DPList plist, int pos)
{
if (pos < 0 || pos >= getLength(plist)) // pos < 0 || pos >= 0;
{
return 0;
}
//找对应位置
Node* pfront = plist;
Node* pCur = nullptr;
int i = 0;
for (i; i < pos; i++)
{
pfront = pfront->next;//front指向删除点之前的位置
}
pCur = pfront->next;
pfront->next = pCur->next;
if (pCur->next != nullptr)
{
pCur->next->prev = pfront;
}
free(pCur);
return 1;
}
5、打印
void Show(DPList plist)
{
Node* pCur = plist->next;
while (pCur != nullptr)
{
printf("%d ", pCur->data);
pCur = pCur->next;
}
printf("\n");
}
6、销毁
void destory(DPList plist)
{
Node* pCur = plist->next;
Node* pNext = nullptr;
while (pCur != nullptr)
{
pNext = pCur->next;
delete pCur;
pCur = pNext;
}
plist->next = nullptr;
}