数据结构之双向链表的形式

数据结构之双向列表的形式

  • 双向链表

提示
博主:来自火星的萨满_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一站式编程中

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值