C语言一个双向链表的实现
首先编写头文件,头文件里做相关的定义和声明,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语言一个双向链表的实现相关推荐
- [js] 请使用 js 实现一个双向链表
[js] 请使用 js 实现一个双向链表 链表结构是我们在面试中经常会被问起的较为基础的数据结构问题,起初学习数据结构使用的是C++语言,最近在做前端面试题的过程中没碰到了需要用js实现双链表的需求, ...
- 8.C语言数据结构 双向链表基本操作
前面学习了如何创建一个双向链表,本节学习有关双向链表的一些基本操作,即如何在双向链表中添加.删除.查找或更改数据元素. 本节知识基于已熟练掌握双向链表创建过程的基础上,我们继续上节所创建的双向链表来学 ...
- C语言一个小小的问题引起的对指针的探究。。。
C语言一个小小的问题引起的对指针的探究... 废话不多说.下面是这个大家认识的一个及其简单的程序: 1 #include <stdio.h> 2 void A(int a[]) 3 { 4 ...
- C语言 一个球从100米高度下落,每次下落反弹原来高度的一半,如此反复,求第10次落地时共经历了多少米?第10次反弹多高?
C语言 一个球从100米高度下落,每次下落反弹原来高度的一半,如此反复,求第10次落地时共经历了多少米?第10次反弹多高? 代码: #include <stdio.h> void main ...
- C++程序设计语言——一个桌面计算器示例
目录 C++程序设计语言--一个桌面计算器示例 程序代码 C++程序设计语言--一个桌面计算器示例 C++程序设计语言一书中第10章 10.2节的桌面计算器示例. 程序代码 #include < ...
- 使用c语言实现双向链表
使用c语言实现双向链表 最近在学习C语言,在学习中,对很多知识又有了新的认识. 我是从java开始学习编程的,现在学了一遍C以后,更坚定了我对自身学习路线的认可. C是你必须要学的一门编程语言,但绝不 ...
- c语言如何删除链表中内容,C语言删除双向链表中数据项程序
创建一个双向链表,并删除此双向链表中的数据项的示例程序,将以下代码保存到一个源文件中:remove_data_from_doubly_linked_list.c, 如下所示 – #include #i ...
- c语言删除双向链表重复元素,求一个双向链表的建立,插入删除的c语言程序完整版的,借鉴一下思想,再多说一下就是能运行的那种...
最佳答案 //链表的操作编辑 //线性表的双向链表存储结构 typedef struct DuLNode { ElemType data; struct DuLNode *prior,*next; } ...
- C语言之 - 双向链表
一.前言 之前,写过一篇<C语言之 - 单向链表>的文章,有兴趣的朋友可以看一下. 双向链表再某些特定的场合结合着单向链表能够非常简便.快速的对数据进行操作,比如有锁队列等. 可以看一下双 ...
最新文章
- android生成大分辨率图片,自动生成Android不同分辨率下的图片
- Java 编程语言中很少被人了解的特性-statement label
- 在Linux上搭建 一个简单的vsftpd服务器
- Linux查看c语言组件进程,Linux下查看进程IO工具iopp
- await,async 我要把它翻个底朝天,这回你总该明白了吧
- 10.类的构造(1)
- 老板不在,你不得不做出越权的决定,咋办?(考试题系列)
- python必备入门代码-小白入门Python开发,必备技能有哪些?
- 从闭包到 语法糖 装饰器
- linux持续检测进程脚本,用于检测进程的shell脚本代码小结
- 算法学习——递归和排列组合
- linux命名管道fifo通信示例
- PAT乙级刷题感想及踩坑总结
- STVD cpstm8 miss } in struct/union definition
- 如何防止输入同样的编号到数据库中(30分)
- Oracle跨平台迁移之XTTS
- 【初级算法】10.有效的数独
- 图片折腾的经历——文件批处理、爬虫、图片工具等
- php拼多多api接口,api.php
- 数学建模方法(2)量纲分析方法