第二章 线性表
大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客
本文原创为亓官劼,请大家支持原创,部分平台一直在盗取博主的文章!!!
博主目前仅在CSDN中写博客,唯一博客更新的地址为:亓官劼的博客
2.4 双向链表(双链表)
在单链表中只有一个指向其后继节点的指针,导致单链表只能从头结点依次顺序的向后遍历,访问后继结点的效率为O(1),但是访问前继结点的效率为O(1),为了解决这个问题,我们引入了双链表。
双链表使用两个指针prior
和next
分别指向前继结点和后继结点。、
双链表存储结点的定义为:
typedef struct DuLNode{
ElemType data;
struct DuLNode* prior, * next;
}DuLNode,*DuLinkList;
双链表插入操作顺序:插入到第i个结点,s为新结点,n指向第i-1个结点
s->next = n->next;
s->prior = n;
n->next = s;// 必须在前两步之后
s->next->prior = s;
双链表插入完整代码:(尾结点的操作和前面的结点操作不一样)
// 双链表插入结点操作
bool InsertDuLNode(DuLinkList& L, int i, ElemType e) {
// 在第i个位置插入元素e
if (i < 1)
return false;
DuLNode* n = L->next;
DuLNode* s = (DuLinkList)malloc(sizeof(DuLNode));//创建新结点
s->data = e;// 为新结点赋值
int j = 1;
while (n && j < i) {// 向后移动到第i-1个位置
n = n->next;
j++;
}
if (j != i - 1) {//没有第i个结点
return false;
}
if (n->next == NULL) {// 插入在最后一个结点
n->next = s;
s->prior = n;
s->next = NULL;
return true;
}
s->next = n->next;
s->prior = n;
n->next = s;
s->next->prior = s;
return true;
}
双链表删除操作:
// 双链表删除操作
bool DeleteDuNode(DuLinkList& L, int i,ElemType &e) {
// 删除双链表第i个结点,并且使用e被删除的结点的值
DuLNode* p = L->next;
int j = 1;
// 序号不对,返回false
if (i < 1) {
return false;
}
while (p && j<i){//移动到第i-1个结点位置
j++;
p = p->next;
}
DuLNode* s = p->next;//记录被删除结点的位置
p->next = s->next;
s->next->prior = p;
free(s);
return true;
}
2.5 循环链表
2.5.1 循环单链表
循环单链表和单链表的区别在于循环单链表的尾结点的指针指向L,而不是NULL。因此循环单链表的判空条件为:L->next == L
。
循环单链表除了表尾的操作,其他的操作和单链表基本一致。但是由于循环单链表是一个环,任何一个地方的插入、删除操作都是一样的,无须判断是否是表尾结点。
因为对单链表常做的操作是在表头和表尾进行的,因此循环单链表设有尾指针r
,这样对于表头和表尾的操作都只需要O(1)。
2.5.2 循环双链表
在循环单链表的基础上,我们还有循环双链表。
在双链表的中,尾结点的下一个指针指向L,就是循环双链表。
循环双链表的判空条件为:p->next == L && p->prior == L
大家好,我叫亓官劼(qí guān jié ),在CSDN中记录学习的点滴历程,时光荏苒,未来可期,加油~博客地址为:亓官劼的博客
本文原创为亓官劼,请大家支持原创,部分平台一直在盗取博主的文章!!!
博主目前仅在CSDN中写博客,唯一博客更新的地址为:亓官劼的博客