学习了前面的单链表之后再学习双向链表就容易理解多了。
概况
在双向链表中,一个节点保存了它前面一个节点,和后面一个节点的索引,可以向前访问,和向后访问。
和单链表比较起来,向前访问更加的方便。
单个节点
在一个节点中呢分为三个区域,第一个区域为prior用来保存前驱节点的地址,第二个区域保存节点中的数据,第三个区域next用来保存后继节点的地址,因为一个节点中保存了前驱和后继节点,那么这个节点就可以通过变量prior和next来分别访问前后节点。
成链
要注意的是,上图为双循环链表,完全可以根据自己的需求来设计双向链表,人是活的嘛。
创建链表
typedef struct node{
int data;
struct node *prior;
struct node *next;
}node;
node *create(int n){
//创建头节点
node *head = (node*)malloc(sizeof(node));
//将移动的p指针指向头节点,以后p都会指向最后一个节点
node *p = head;
//初始化头节点
head->prior = NULL;
head->next = NULL;
int i;
//初始化数据
for(i = 1; i <= n; i++){
//创建新的节点
node *s = (node*)malloc(sizeof(node));
//写入数据
s->data = i;
//将新的的节点的前驱指向为最后一个节点
s->prior = p;
//将最后一个节点的后继节点指向为新的节点
p->next = s;
//连接成功后又将p指向新的节点(也是现在链表的最后一个节点)
p = s;
}
//将最后一个节点的后继节点指向为头节点
p->next = head;
//将头节点的前驱指向为最后一个节点节点,在这里形成环
head->prior = p;
return head;
}
插入操作
void insert(node *head,int index, int data){
node *target;
//查找标记
int count = 1;
//使用for循环查找对应位置
for(target = head->next; target != head; target = target->next,count++){
if(count == index){
//创建新的的节点
node *s = (node*)malloc(sizeof(node));
s->data = data;
/*第一步,将新节点的后继指向目标位置,表示将新节点插入
目标节点的前面*/
s->next = target;
//第二步,新节点的前驱节点指向为目标节点的前驱节点
s->prior = target->prior;
//第三步,目标节点的前驱节点后继节点指向为新节点
target->prior->next = s;
//第四步,目标节点的前驱节点设置为新节点
target->prior = s;
}
}
}
注意上面的顺序很重要,比如,如果先执行第四步,那么我们就不能够通过目标节点的前驱节点找到目标节点的前一个节点,整个链也就断了。
删除操作
void deleteNode(node *head, int index){
node *target;
//查找标记
int count = 1;
//使用for循环查找对应位置
for(target = head->next; target != head; target = target->next,count++){
if(count == index){
//第一步
target->prior->next = target->next;
//第二步
target->next->prior = target->prior;
free(target);
}
}
}
在理解了插入节点的基础上,理解删除就很容易了,断绝目标节点和他相邻节点的关系就OK啦,最后别忘记了重新连接两个相邻节点。