首先编写头文件,头文件里做相关的定义和声明,DList.h内容如下:

#ifndef DList_H
#define DList_H
typedef  int Item;
typedef struct Node * PNode;
typedef PNode Position;
/*定义节点类型*/
typedef struct Node
{  Item data;      /*数据域*/ PNode previous; /*指向前驱*/ PNode next;     /*指向后继*/
}Node;
/*定义链表类型*/
typedef struct
{  PNode head;     /*指向头节点*/ PNode tail;     /*指向尾节点*/ int size;
}DList;  /*分配值为i的节点,并返回节点地址*/
Position MakeNode(Item i);  /*释放p所指的节点*/
void FreeNode(PNode p);  /*构造一个空的双向链表*/
DList* InitList();  /*摧毁一个双向链表*/
void DestroyList(DList *plist);  /*将一个链表置为空表,释放原链表节点空间*/
void ClearList(DList *plist);  /*返回头节点地址*/
Position GetHead(DList *plist);  /*返回尾节点地址*/
Position GetTail(DList *plist);  /*返回链表大小*/
int GetSize(DList *plist);  /*返回p的直接后继位置*/
Position GetNext(Position p);  /*返回p的直接前驱位置*/
Position GetPrevious(Position p);  /*将pnode所指节点插入第一个节点之前*/
PNode InsFirst(DList *plist,PNode pnode);  /*将链表第一个节点删除并返回其地址*/
PNode DelFirst(DList *plist);  /*获得节点的数据项*/
Item GetItem(Position p);  /*设置节点的数据项*/
void SetItem(Position p,Item i);  /*删除链表中的尾节点并返回其地址,改变链表的尾指针指向新的尾节点*/
PNode Remove(DList *plist);  /*在链表中p位置之前插入新节点S*/
PNode InsBefore(DList *plist,Position p,PNode s);  /*在链表中p位置之后插入新节点s*/
PNode InsAfter(DList *plist,Position p,PNode s);  /*返回在链表中第i个节点的位置*/
PNode LocatePos(DList *plist,int i);  /*依次对链表中每个元素调用函数visit()*/
void ListTraverse(DList *plist,void (*visit)());
#endif 

接下来逐个实现其功能,DList.c内容如下:

#include"DList.h"
#include<malloc.h>
#include<stdlib.h>
/*分配值为i的节点,并返回节点地址*/
Position MakeNode(Item i)
{  PNode p = NULL;   p = (PNode)malloc(sizeof(Node));  if(p!=NULL)  {  p->data = i;  p->previous = NULL;  p->next = NULL;  }     return p;
}
/*释放p所指的节点*/
void FreeNode(PNode p)
{  free(p);
}
/*构造一个空的双向链表*/
DList * InitList()
{  DList *plist = (DList *)malloc(sizeof(DList));  PNode head = MakeNode(0);   if(plist!=NULL)  {  if(head!=NULL)  {  plist->head = head;  plist->tail = head;  plist->size = 0;  }  else return NULL;  }  return plist;
}  /*摧毁一个双向链表*/
void DestroyList(DList *plist)
{  ClearList(plist);  free(GetHead(plist));  free(plist);
}  /*判断链表是否为空表*/
int IsEmpty(DList *plist)
{  if(GetSize(plist)==0&&GetTail(plist)==GetHead(plist))  return 1;  else return 0;
}
/*将一个链表置为空表,释放原链表节点空间*/
void ClearList(DList *plist)
{  PNode temp,p;  p = GetTail(plist);  while(!IsEmpty(plist))  {     temp = GetPrevious(p);  FreeNode(p);  p = temp;  plist->tail = temp;  plist->size--;  }
}  /*返回头节点地址*/
Position GetHead(DList *plist)
{  return plist->head;
}  /*返回尾节点地址*/
Position GetTail(DList *plist)
{  return plist->tail;
}  /*返回链表大小*/
int GetSize(DList *plist)
{  return plist->size;
}  /*返回p的直接后继位置*/
Position GetNext(Position p)
{  return p->next;
}  /*返回p的直接前驱位置*/
Position GetPrevious(Position p)
{  return p->previous;
}  /*将pnode所指节点插入第一个节点之前*/
PNode InsFirst(DList *plist,PNode pnode)
{  Position head = GetHead(plist);  if(IsEmpty(plist))  plist->tail = pnode;  plist->size++;  pnode->next = head->next;  pnode->previous = head;  if(head->next!=NULL)  head->next->previous = pnode;  head->next = pnode;  return pnode;
}  /*将链表第一个节点删除,返回该节点的地址*/
PNode DelFirst(DList *plist)
{  Position head = GetHead(plist);  Position p=head->next;  if(p!=NULL)  {  if(p==GetTail(plist))  plist->tail = p->previous;  head->next = p->next;  head->next->previous = head;  plist->size--;  }     return p;
}  /*获得节点的数据项*/
Item GetItem(Position p)
{  return p->data;
}  /*设置节点的数据项*/
void SetItem(Position p,Item i)
{  p->data = i;
}  /*删除链表中的尾节点并返回地址,改变链表的尾指针指向新的尾节点*/
PNode Remove(DList *plist)
{  Position p=NULL;  if(IsEmpty(plist))  return NULL;  else {  p = GetTail(plist);  p->previous->next = p->next;  plist->tail = p->previous;  plist->size--;  return p;  }
}
/*在链表中p位置之前插入新节点s*/
PNode InsBefore(DList *plist,Position p,PNode s)
{  s->previous = p->previous;  s->next = p;  p->previous->next = s;      p->previous = s;  plist->size++;  return s;
}
/*在链表中p位置之后插入新节点s*/
PNode InsAfter(DList *plist,Position p,PNode s)
{  s->next = p->next;  s->previous = p;  if(p->next != NULL)  p->next->previous = s;  p->next = s;  if(p = GetTail(plist))  plist->tail = s;  plist->size++;  return s;
}  /*返回在链表中第i个节点的位置*/
PNode LocatePos(DList *plist,int i)
{  int cnt = 0;  Position p = GetHead(plist);  if(i>GetSize(plist)||i<1)  return NULL;  while(++cnt<=i)  {  p=p->next;  }  return p;
}  /*依次对链表中每个元素调用函数visit()*/
void ListTraverse(DList *plist,void (*visit)())
{  Position p = GetHead(plist);  if(IsEmpty(plist))  exit(0);  else {  while(p->next!=NULL)  {  p = p->next;  visit(p->data);            }         }
}


接下来进行测试,Test.c内容如下:

#include"DList.h"
#include<stdio.h>
void print(Item i)
{  printf("数据项为%d n",i);
}
main()
{  DList *plist = NULL;  PNode p = NULL;  plist = InitList();  p = InsFirst(plist,MakeNode(1));  InsBefore(plist,p,MakeNode(2));  InsAfter(plist,p,MakeNode(3));  printf("p前驱位置的值为%dn",GetItem(GetPrevious(p)));  printf("p位置的值为%dn",GetItem(p));  printf("p后继位置的值为%dn",GetItem(GetNext(p)));  printf("遍历输出各节点数据项:n");  ListTraverse(plist,print);  printf("除了头节点该链表共有%d个节点n",GetSize(plist));  FreeNode(DelFirst(plist));  printf("删除第一个节点后重新遍历输出为:n");  ListTraverse(plist,print);  printf("除了头节点该链表共有%d个节点n",GetSize(plist));  DestroyList(plist);  printf("链表已被销毁n");
}  

C语言一个双向链表的实现相关推荐

  1. [js] 请使用 js 实现一个双向链表

    [js] 请使用 js 实现一个双向链表 链表结构是我们在面试中经常会被问起的较为基础的数据结构问题,起初学习数据结构使用的是C++语言,最近在做前端面试题的过程中没碰到了需要用js实现双链表的需求, ...

  2. 8.C语言数据结构 双向链表基本操作

    前面学习了如何创建一个双向链表,本节学习有关双向链表的一些基本操作,即如何在双向链表中添加.删除.查找或更改数据元素. 本节知识基于已熟练掌握双向链表创建过程的基础上,我们继续上节所创建的双向链表来学 ...

  3. C语言一个小小的问题引起的对指针的探究。。。

    C语言一个小小的问题引起的对指针的探究... 废话不多说.下面是这个大家认识的一个及其简单的程序: 1 #include <stdio.h> 2 void A(int a[]) 3 { 4 ...

  4. C语言 一个球从100米高度下落,每次下落反弹原来高度的一半,如此反复,求第10次落地时共经历了多少米?第10次反弹多高?

    C语言 一个球从100米高度下落,每次下落反弹原来高度的一半,如此反复,求第10次落地时共经历了多少米?第10次反弹多高? 代码: #include <stdio.h> void main ...

  5. C++程序设计语言——一个桌面计算器示例

    目录 C++程序设计语言--一个桌面计算器示例 程序代码 C++程序设计语言--一个桌面计算器示例 C++程序设计语言一书中第10章 10.2节的桌面计算器示例. 程序代码 #include < ...

  6. 使用c语言实现双向链表

    使用c语言实现双向链表 最近在学习C语言,在学习中,对很多知识又有了新的认识. 我是从java开始学习编程的,现在学了一遍C以后,更坚定了我对自身学习路线的认可. C是你必须要学的一门编程语言,但绝不 ...

  7. c语言如何删除链表中内容,C语言删除双向链表中数据项程序

    创建一个双向链表,并删除此双向链表中的数据项的示例程序,将以下代码保存到一个源文件中:remove_data_from_doubly_linked_list.c, 如下所示 – #include #i ...

  8. c语言删除双向链表重复元素,求一个双向链表的建立,插入删除的c语言程序完整版的,借鉴一下思想,再多说一下就是能运行的那种...

    最佳答案 //链表的操作编辑 //线性表的双向链表存储结构 typedef struct DuLNode { ElemType data; struct DuLNode *prior,*next; } ...

  9. C语言之 - 双向链表

    一.前言 之前,写过一篇<C语言之 - 单向链表>的文章,有兴趣的朋友可以看一下. 双向链表再某些特定的场合结合着单向链表能够非常简便.快速的对数据进行操作,比如有锁队列等. 可以看一下双 ...

最新文章

  1. android生成大分辨率图片,自动生成Android不同分辨率下的图片
  2. Java 编程语言中很少被人了解的特性-statement label
  3. 在Linux上搭建 一个简单的vsftpd服务器
  4. Linux查看c语言组件进程,Linux下查看进程IO工具iopp
  5. await,async 我要把它翻个底朝天,这回你总该明白了吧
  6. 10.类的构造(1)
  7. 老板不在,你不得不做出越权的决定,咋办?(考试题系列)
  8. python必备入门代码-小白入门Python开发,必备技能有哪些?
  9. 从闭包到 语法糖 装饰器
  10. linux持续检测进程脚本,用于检测进程的shell脚本代码小结
  11. 算法学习——递归和排列组合
  12. linux命名管道fifo通信示例
  13. PAT乙级刷题感想及踩坑总结
  14. STVD cpstm8 miss } in struct/union definition
  15. 如何防止输入同样的编号到数据库中(30分)
  16. Oracle跨平台迁移之XTTS
  17. 【初级算法】10.有效的数独
  18. 图片折腾的经历——文件批处理、爬虫、图片工具等
  19. php拼多多api接口,api.php
  20. 数学建模方法(2)量纲分析方法

热门文章

  1. HAProxy入门及常用配置模拟测试
  2. shell中sed命令的用法
  3. bzoj 2109 amp; 2535 空中管制 解读
  4. JS Math.sin() 与 Math.cos()
  5. activeMq 安装
  6. 轻松搭建博客平台-开源ASP.NET 博客Subtext 的安装
  7. windows上安装Anaconda和python的教程详解
  8. 两行 CSS 代码实现图片任意颜色赋色技术
  9. Nmcli 网络管理命令行工具基础
  10. CoFun 1612 单词分组(容斥)