数据结构 双向链表 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();
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语言实现的更多相关文章
- 数据结构算法C语言实现(二十七)--- 7.2图的遍历
一.简述 栈与队列,DFS与BFS.仅以连接表为例实现. 二.头文件 BFS要用到的头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@g ...
- 数据结构算法C语言实现(二十)--- 6.3.1遍历二叉树
一.简述 二叉树的遍历主要是先序.中序.后序及对应的递归和非递归算法,共3x2=6种,其中后序非递归在实现上稍复杂一些.二叉树的遍历是理解和学习递归及体会栈的工作原理的绝佳工具! 此外,非递归所用的栈 ...
- 数据结构算法C语言实现(十二)--- 3.4循环队列&队列的顺序表示和实现
一.简述 空队列的处理方法:1.另设一个标志位以区别队列是空还是满:2.少用一个元素空间,约定以队列头指针在队尾指针下一位置上作为队列呈满的状态的标志. 二.头文件 //3_4_part1.h /** ...
- 数据结构算法C语言实现(十一)--- 3.4队列的链式表示和实现
一.简介 FIFO. 二.头文件 //3_4_part1.h /** author:zhaoyu email:zhaoyu1995.com@gmail.com date:2016-6-9 note:r ...
- 数据结构算法C语言实现(十)--- 3.3栈与递归的实现
一.简介 汉诺塔问题是递归的一个典型例子,而且书上的讲解很详细,对理解C语言函数及函数传参的工作机制很有帮助,值得一看.而且,递归在我看来和分治.DP.贪心等一样是十分优美的思想,值得学习!!! 二. ...
- 数据结构算法C语言实现(八)--- 3.2栈的应用举例:迷宫求解与表达式求值
一.简介 迷宫求解:类似图的DFS.具体的算法思路可以参考书上的50.51页,不过书上只说了粗略的算法,实现起来还是有很多细节需要注意.大多数只是给了个抽象的名字,甚至参数类型,返回值也没说的很清楚, ...
- 数据结构算法C语言实现(七)--- 3.1栈的线性实现及应用举例
一.简述 栈,LIFO.是操作受限的线性表,和线性表一样有两种存储表示方法.下面以顺序存储为例,实现. 二.ADT 暂无. 三.头文件 //3_1.h /** author:zhaoyu email: ...
- 数据结构算法C语言实现(六)---2.4一元多项式的表示及相加
一.简述 利用链表表示稀疏多项式,并基于之前的一些操作(编程实现上还是有所不同的)组合新的操作实现一元多项式的表示及相加. 二.ADT 抽象数据类型一元多项式的定义 ADT Polyomail{ 数据 ...
- 数据结构算法C语言实现(五)---2.3重新定义线性链表及其基本操作
一.简述 ...由于链表在空间的合理利用上和插入.删除时不需要移动等的优点,因此在很多场合下,它是线性表的首选存储结构.然而,它也存在着实现某些基本操作,如求线性表的长度时不如顺序存储结构的缺点:另一 ...
随机推荐
- Java 集合存储都返回什么?
1.抛出一个类 package com.math.spring; import com.google.common.collect.Lists; import com.google.common.co ...
- hdu 5187 zhx's contest (快速幂+快速乘)
zhx's contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) To ...
- DP基础(线性DP)总结
DP基础(线性DP)总结 前言:虽然确实有点基础......但凡事得脚踏实地地做,基础不牢,地动山摇,,,嗯! LIS(最长上升子序列) dp方程:dp[i]=max{dp[j]+1,a[j]< ...
- kubernetes 之部署metrics-server v0.3.1
Metrics-server简介 Metrics-server是用来替换heapster获取集群上资源指标数据的,heapster从1.11开始逐渐被废弃了. 在使用heapster时,获取资源指标是 ...
- c++继承子类构造函数问题
c++中子类在继承基类的时候需要在构造函数中初始化变量.如果基类没有构造函数或者只有不带参数的构造函数,那么子类中的构造函数就不需要调用基类的构造函数了. 个人总结了两点子类中构造函数必须调用父类的构 ...
- FTP基础
FTP服务 只要有一种数据存储格式 :解析库 ,不同解析库需要不同查询方式 nsswitch 框架 平台 (每一种程序自己不再负责实时名称解析的功能,而是将这种功能委托给nsswitch) S/M ...
- Rhel7.4系统部署cobbler
cobbler安装 一.系统信息: [root@openstack ~]# cat /etc/redhat-release Red Hat Enterprise Linux Server releas ...
- Atcoder ABC138
Atcoder ABC138 A .Red or Not 一道网速题. 大于3200输出原字符串,否则就输出red. #include<iostream> #include<cstd ...
- 【平台中间件】为什么用etcd而不用ZooKeeper?从应用场景到实现原理的全方位解读
前言 博主在工作过程中经常接触到ETCD,搜索相关资料的时候发现排名最高的是一篇图片全是404的转载文章,后来看到了原文,感觉有义务让更多的人看到这样的精品文章,所以进行了转载. 原文发布在infoQ ...
- shell之列表的定义与循环
字符串列表定义方法1: a=(f1 f2 f3 f4)for i in ${a[*]}#遍历每一个列表值 for i in ${a[@]}#等价与上一句 实例: #!bin/basha=(f1 f2 ...