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();
if(plist!=NULL)
{
if(head!=NULL)
{
plist->head = head;
plist->tail = head;
plist->size = ;
}
else
return NULL;
}
return plist;
} /*摧毁一个双向链表*/
void DestroyList(DList *plist)
{
ClearList(plist);
free(GetHead(plist));
free(plist);
} /*判断链表是否为空表*/
int IsEmpty(DList *plist)
{
if(GetSize(plist) == && GetTail(plist) == GetHead(plist))
return ;
else
return ;
}
/*将一个链表置为空表,释放原链表节点空间*/
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 = ;
Position p = GetHead(plist);
if(i>GetSize(plist)||i<)
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();
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);
}
int main()
{
DList *plist = NULL;
PNode p = NULL; plist = InitList();
p = InsFirst(plist,MakeNode());
InsBefore(plist,p,MakeNode());
InsAfter(plist,p,MakeNode()); printf("p前驱位置的值为%d\n",GetItem(GetPrevious(p)));
printf("p位置的值为%d\n",GetItem(p));
printf("p后继位置的值为%d\n",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");
}

运行结果:

[walt740@localhost .Doublylinklist]$ gcc test.c dlist.c dlist.h -o test
[walt740@localhost .Doublylinklist]$ tree -L
.
├── dlist.c
├── dlist.h
├── test
├── test.c
└── \\\\\\\\\\\\
├── bin
├── obj
├── \\\\\\\\\\\\.cbp
├── \\\\\\\\\\\\.depend
└── \\\\\\\\\\\\.layout directories, files
[walt740@localhost .Doublylinklist]$ ./test
p前驱位置的值为2
p位置的值为1
p后继位置的值为3
遍历输出各节点数据项:
数据项为2
数据项为1
数据项为3
除了头节点该链表共有3个节点
删除第一个节点后重新遍历输出为:
数据项为1
数据项为3
除了头节点该链表共有2个节点
链表已被销毁
[walt740@localhost .Doublylinklist]$ ^

转自 -- http://blog.csdn.net/hopeyouknow/article/details/6716177

数据结构 双向链表 C语言实现的更多相关文章

  1. 数据结构算法C语言实现(二十七)--- 7.2图的遍历

    一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...

  2. 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树

    一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...

  3. 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现

    一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...

  4. 数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现

    一.简介 FIFO. 二.头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@gmail.com date:2016-6-9 note:r ...

  5. 数据结构算法C语言实现(十)--- 3.3栈与递归的实现

    一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...

  6. 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值

    一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...

  7. 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例

    一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...

  8. 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加

    一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...

  9. 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作

    一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...

随机推荐

  1. CodeForces 835C - Star sky | Codeforces Round #427 (Div. 2)

    s <= c是最骚的,数组在那一维开了10,第八组样例直接爆了- - /* CodeForces 835C - Star sky [ 前缀和,容斥 ] | Codeforces Round #4 ...

  2. Codeforces Round #455 (Div. 2) 909D. Colorful Points

    题 OvO http://codeforces.com/contest/909/problem/D CF 455 div2 D CF 909D 解 算出模拟的复杂度之后就是一个很水的模拟题 把字符串按 ...

  3. sb 的长度 和 文件大小

    StringBuilder sb = new StringBuilder(); ;i<;i++)  //1 0000 0000  1亿项 { sb.AppendFormat("{0}, ...

  4. C++自定义方法类、调用

    如求矩形.圆的面积的方法,可以写成一个area类 area.h中只声明,不实现: #ifndef AREA_H //防止重复引用 #define AREA_H class area{//自定义类 pu ...

  5. 014_linuxC++之_不同类型的继承

    #include <iostream> #include <string.h> #include <unistd.h> using namespace std; c ...

  6. 【线性代数】4-2:投影(Porjections)

    title: [线性代数]4-2:投影(Porjections) categories: Mathematic Linear Algebra keywords: Projections Project ...

  7. 源码安装ROS Melodic Python3 指南 (转) + 安装记录

    这篇文章转自   https://blog.csdn.net/id9502/article/details/80410989  csdn真是作大死,我保存这篇博客的时候还不需要花钱就能看,现在居然要v ...

  8. 阿里云Ubuntu安装Composer和中国镜像

    引用: Composer是PHP用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件. PHP ...

  9. ACM之路(14)—— 线段树的日常(上)

    我的线段树简直有毒,各种错误都能忙上半天.做了kuangbin的线段树专题的一半,还有一半留到以后去做. 链接:http://acm.hust.edu.cn/vjudge/contest/view.a ...

  10. CF258B

    CF258B 题意: 7个人在 $ [1,m] $ 区间内取数,求第一个人选的数的4和7的个数大于其他人的4和7个数总和的方案数. 解法: 要求输入的 $ m $ 可以很大,而且需要按位考虑每隔人的贡 ...