数据结构之双向列表的形式
- 双向链表
提示
博主:来自火星的萨满_906285288
博客地址:http://blog.csdn.net/qq_29924041
概念
在上一篇幅博客中,是关于单向链表的讲解,以及从linuxC一站式编程中引入的例子,那么除了单向链表之外,还有一个叫做双向链表的东西。
单向链表的删除,从前一篇的案例中可以看到,其实就是要摘除这个节点的前趋势,而在单向链表中,如果需要找到某个链表的前驱的话,这个时候是需要从表头,也就是head部分开始进行查找,对于n个节点的链表来说,如果删除的话,其时间的复杂度相当高。那么就需要引入双向链表的概念。
双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表
从概念中其实就可以看出来,对于单向链表的话,只有一个指针指向后继,而在双向链表过程中,其实有两个指针,一个是指向了前驱pre,一个是指向了后继next,注意,这里的前驱和后继都是直接后继。
如下图所示:
从上图中就可以看到,双向链表其实也就是在单向链表中添加了一个指向头的pre指针,这样保证了当前的节点既能够指向下一个节点,也能够指向前一个节点。
代码实例
/*
* ===========================================================================
*
* Filename: linkedlist.h
* Description: µ•¡¥±ÌµƒΩ·ππÕ∑Œƒº˛µƒ∂®“Â
* Version: 1.0
* Created: 2018ƒÍ01‘¬20»’ 21 ±45∑÷27√Î
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#ifndef __DOUBLELINKEDLIST_H_
#define __DOUBLELINKEDLIST_H_
typedef struct node* link;
struct node{
unsigned char item;
link prev,next;
};
link make_node(unsigned char item);
void free_node(link p);
link search(unsigned char key);
void insert(link p);
void delete(link p);
void traverse(void(*visit)(link));
void destory(void);
void enqueue(link p);
link dequeue(void);
#endif
/*
* ===========================================================================
*
* Filename: doublelinkedlist.c
* Description:
* Version: 1.0
* Created: 2018ƒÍ01‘¬20»’ 21 ±51∑÷30√Î
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include<stdlib.h>
#include "doublelinkedlist.h"
struct node tailsentinel;
struct node headsentinel = {0,NULL,&tailsentinel};
struct node tailsentinel = {0,&headsentinel,NULL};
static link head = &headsentinel;
static link tail = &tailsentinel;
link make_node(unsigned char item){
link p = (link)malloc(sizeof(*p));
if(p == NULL){
perror("malloc link error");
exit(0);
}
p->item = item;
p->prev = p->next = NULL;
return p;
}
void free_node(link p){
if(p != NULL)
free(p);
}
link search(unsigned char key){
link p ;
for(p = head -> next; p!=tail ; p=p->next){
if(p->item == key){
return p;
}
}
return NULL;
}
void insert(link p){
p->next = head->next;
head->next->prev = p;
head->next=p;
p->prev = head;
}
void delete(link p){
p->prev->next = p->next;
p->next->prev = p->prev;
}
void traverse(void(*visit)(link)){
link p;
for(p = head->next;p!=tail;p = p->next){
visit(p);
}
}
void destory(void){
link q,p = head->next;
head->next = tail;
tail->prev = head;
while(p!=tail){
q = p;
p = p -> next;
free_node(q);
}
}
void enqueue(link p){
insert(p);
}
link dequeue(void){
if(tail->prev == head){
return NULL;
}else{
link p = tail->prev;
delete(p);
return p;
}
}
/*
* ===========================================================================
*
* Filename: main.c
* Description:
* Version: 1.0
* Created: 2018ƒÍ01‘¬20»’ 22 ±06∑÷31√Î
* Revision: none
* Compiler: gcc
* Author: (),
* Company:
*
* ===========================================================================
*/
#include<stdio.h>
#include"doublelinkedlist.h"
void print_item(link p){
printf("prev:%p\n",p->prev);
printf("%d\n",p->item);
printf("next:%p\n",p->next);
}
int main(int argc,char*argv[]){
link p = make_node(10);
insert(p);
p = make_node(5);
printf("p:%p\n",&p);
insert(p);
p = make_node(90);
printf("p:%p\n",&p);
insert(p);
traverse(print_item);
printf("====");
p = search(5);
delete(p);
free_node(p);
traverse(print_item);
destory();
p = make_node(100);
enqueue(p);
p = make_node(200);
enqueue(p);
p = make_node(250);
enqueue(p);
while(p = dequeue()){
print_item(p);
free_node(p);
}
return 0;
}
实例代码取自linuxC一站式编程中