双链表的没一个元素都是对象,每个对象包含一个关键字域和两个指针域(next,prev)。当然,每个对象还可能包含一些其他的卫星数据。next指向后继节点,prev指向前驱节点。如果prev[x] == null,则无前驱节点,是head头节点。如果next[x] == null则无后继节点,是最后一个节点,即尾节点tail。
双链表的具体操作如下:
双向链表的插入:insert(L, x)
next[x]=head[L] //头插法,当前节点x的下一个节点指向头节点
if head[L] != null // 头节点不为空
then prev[head[L]] = x //头节点的上一个节点指向x
head[L] = x //重置头节点
prev[x] = null //头节点的上一个节点置为空
搜索:
search(L, k)
x = head[L]
while x != null and key[x] != k
do x = next[x]
return x;
删除:
delete(L, x)
if(prev[x] != null) //如果当前节点不是头节点
then next[prev[x]] = next[x] //当前节点x的上个节点的下一个节点置为当前节点x的下一个节点
else head[L] = next[x] //否则头节点置为当前节点x的下一个节点
if next[x] != null
then prev[next[x]] = prev[x] // 当前节点x的下个节点的上一个节点置为当前节点x的上一个节点
哨兵nil[L],有其他元素一样的各个域
可以简化边界条件,将双向链表变成带哨兵的环形双向链表,哨兵元素介于头和尾之间,next[nil[L]]指向头节点,prev[nil[L]]指向尾节点,同样表头的prev域和表尾的next域都指向nil[L],这样可以吧head[L]换成next[nil[L]]。
插入:
next[x] = next[nil[L]]
prev[next[nil[L]] = x
next[nil[L]] = x
prev[x] = null
删除:
next[prev[x]] = next[x]
prev[next[x]] = prev[x]