双向链表:要考虑头,也要考虑尾。
删除、插入元素的时候,常常需分情况讨论。
- 这是第一个元素吗?
- 这是最后一个元素吗?
- 这是中间的元素吗?
双向链表的基本操作(以下双向链表是带头结点的双向链表)
(1)链表的初始化
因为该双向链表为带头结点的链表,而头结点的内容并没有实际意义,所以初始化时创建结点赋值为0;代码如下:
void DListInit(PDLNode* pHead){ // pHead永远不可能为空
assert(pHead);
*pHead = (PDLNode)malloc(sizeof(DLNode));//给出头结点
if (NULL == *pHead){ //判空
assert(0);
return;
}
//解引用得到外部实参地址
(*pHead)->_pNext = *pHead;//下一个元素指向它自己(空链表下)
(*pHead)->_pPre = *pHead;//前一个元素也指向它自己(空链表下)
}
PDLNode BuyDListNode(DLDataType data){
PDLNode pNewNode = (PDLNode)malloc(sizeof(DLNode));
if (NULL == pNewNode){
assert(0);
return;
}
pNewNode->_pNext = NULL;//新节点的下一个节点并不清楚
pNewNode->_pPre = NULL;
}
(2)尾插
思想:首先创建一个新结点,再定义一个指针使之指向最后一个元素,双向链表的头指针的最后一个元素,然后修改头指针与新插入的结点指针间的指向,还有最后一个元素与新插入的结点指针间的指向,还有最后一个元素与新插入的结点之间的指向。代码如下:
void DListPushBack(PDLNode pHead, DLDataType data){
PDLNode pNewNode = BuyDListNode(data);//新节点传进去
pNewNode->_pNext = pHead;
pNewNode->_pPre = pHead->_pPre;//head的前一个节点就是原来的最后一个节点
pHead->_pPre->_pNext = pNewNode;
pHead->_pPre = pNewNode;
}
(3)尾删
思想:定义一个指针使之指向最后一个元素既要删除的元素,在定义一个指针使之指向倒数第二个元素,修改头指针与倒数第二个结点之间的指针指向,最后销毁最后一个结点。代码如下:
void DListPopBack(PDLNode pHead){
PDLNode pDelNode = NULL;
assert(pHead);
if (pHead == pHead->_pNext)//指向自己,删不了就返回
return;
PDLNode pDelNode = pHead->_pPre;
pDelNode->_pPre->_pNext = pHead;
pHead->_pPre = pDelNode->_pPre;
free(pDelNode);
}
(4)头插
思想:首先创建一个新结点,在定义一个指针使之指向第一个元素,双向链表的头指针的next即为第一个元素,然后修改头指针与新插入的结点指针间的指向,还有第一个元素与新插入的节点之间的指向。代码如下:
void DListPushFront(PDLNode pHead, DLDataType data)
{
PDLNode pNewNode = BuyDListNode(data);//先给一个新元素data
pNewNode->_pNext = pHead->_pNext;
pNewNode->_pPre = pHead;
pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
(5)头删
思想:定义一个指针使之指向第一个元素既要删除的元素,再定义一个指针指向第二个元素,修改头指针与第二个结点之间的指针指向,最后销毁第一个结点。代码如下:
void DListPopFront(PDLNode pHead){
PDLNode pDelNode = NULL;
assert(pHead);
if (pHead->_pNext == pHead)//空链表删出不了,直接返回
return;
PDLNode pDelNode = pHead->_pNext;
pHead->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = pHead;
free(pHead);
}
(6)给定一个位置pos,插入一个元素
思想:先创建一个新结点,再定义一个指针使之指向pos的前一个元素,然后修改pos与新插入的结点指针的指向和指向pos之前的元素的指针与新结点之间指针的指向。代码如下:
void DListInsert(PDLNode pos, DLDataType data){
PDLNode pNewNode = NULL;
if (NULL == pos)
return;
PDLNode pNewNode = BuyDListNode(data);
pNewNode->_pNext = pos;
pNewNode->_pPre = pos->_pPre;
pos->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
}
~继续努力!bye~