双向链表
如何求链表中p结点的直接前驱,其时间性能如何?
从当前结点循环遍历判断p结点的直接前驱,时间复杂度为O(n)。
通过p->next可以直接访问p结点的后继结点,时间复杂度为O(1)。
如何快速获取p结点的前驱结点?
通过结点添加指针域指向前驱结点。
双链表:在单链表的每个结点中在设置一个指针域,指向其前驱结点.
data:存放数据元素; next:存放该节点后继结点地址; prior:存储该节点前驱结点地址。
双向链表定义节点结构:
typedef strcut DuLNode{
ElemType data; //数据域
struct PuLNode *prior; //指向前驱结点的指针
struct PuLNode *next; //指向后继结点的指针
}DuLNode, *DuLinkList;
双向链表的插入操作:
s结点的前驱指针指向p结点,p结点原来的后继指针重新指向s的前驱指针域,原来的后继指向赋给s的后继指针域。
s->prior = p; s->next->prior=s; //s->next原来为a[i]结点,a[i]结点的prior指针域指向s结点
s->next = p->next; //指针域重新赋值
双向链表插入操作: 在第i个位置后插入结点e
bool ListInsert_DuL(DuLinkList &L , int i, ElemType e){
if(!(p = GetElem_DuL(L,i)))) //查找第i个元素的结点吗,操作和单链表一样
return false;
s = (List)malloc(sizeof(DuLNode)); //分配新节点s内存空间
s->data = e;
s->next = p->next;
p->next->prior = s;
p->next = s;
return true;
}
删除第i个节点的操作:
Demo:
bool ListDelete_Dul(DuLinkList &L, int i, ElemType e){
p->prior->next = p->next; //第一步
p->next->prior = p->prior; //第二步
free(p); //释放p结点的内存空间
return true;
}
虽然双向链表的运算执行效率较高,但是每个结点都需要占用额外的一个指针域,空间复杂度翻倍。