0.

弄完了单链表,在看双向链表。怎么整?多写,多想,想不通画出来在想,再写,再模仿~

1.  没啥说的,敲代码~

 说点啥呢,注意自己的代码风格哦,要符合"潮流",不要独树一帜

1.1

DList.h

#ifndef _DLIST_H_
#define _DLIST_H_ typedef int data_t; /*节点指针*/
typedef struct node_t * PNode; /*表示返回的是地址*/
typedef PNode Position; /*定义节点类型*/
typedef struct node_t {
data_t data; // 数据域
PNode prev; // 前驱指针
PNode next; // 后继指针
}node_t; /*定义链表类型*/
typedef struct DList {
PNode head; // 指向头节点
PNode tail; // 指向尾节点
int size;
}DList; /*分配值为i的节点 并返回节点地址*/
Position MakeNode(data_t 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 GetPrev(Position p); /*将pnode所指的节点插入第一个节点之前*/
PNode InsFirst(DList * plist, PNode pnode); /*将链表第一个节点删除并返回其地址*/
PNode DelFirst(DList * plist); /*返回节点的数据项*/
data_t GetData(Position p); /*设置节点的数据项*/
void SetData(Position p, data_t i); /*删除链表中的尾节点并返回其地址 改变链表的尾指针指向新的尾节点*/
PNode DelTail(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_H_

DList.c

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h> #include "DList.h" /*分配值为i的节点 并返回节点地址*/
Position
MakeNode(data_t i)
{
PNode p = NULL;
p = (PNode)malloc(sizeof(node_t)); // 给节点分配内存
if(p!=NULL) {
p->data = i;
p->prev = 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 = GetPrev(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
GetPrev(Position p)
{
return p->prev;
} /*将pnode所指的节点插入第一个节点之前*/
PNode
InsFirst(DList * plist, PNode pnode)
{
Position head = GetHead(plist); if(IsEmpty(plist))
plist->tail = pnode;
plist->size++; pnode->next = head->next;
pnode->prev = head; if(head->next!=NULL) //
head->next->prev = 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->prev;
head->next = p->next;
head->next->prev = head;
plist->size--;
} return p;
} /*返回节点的数据项*/
data_t
GetData(Position p)
{
return p->data;
} /*设置节点的数据项*/
void
SetData(Position p, data_t i)
{
p->data = i;
} /*删除链表中的尾节点并返回其地址 改变链表的尾指针指向新的尾节点*/
PNode
DelTail(DList * plist)
{
Position p = NULL;
if(IsEmpty(plist))
return NULL;
else {
p = GetTail(plist);
p->prev->next = p->next;
plist->tail = p->prev;
plist->size--; return p;
}
} /*在链表中p位置之前插入节点s*/
PNode
InsBefore(DList * plist, Position p, PNode s)
{
s->prev = p->prev;
s->next = p;
p->prev->next = s;
p->prev = s; plist->size++; return s;
} /*在链表中p位置之后插入节点s*/
PNode
InsAfter(DList * plist, Position p, PNode s)
{
s->next = p->next;
s->prev = p; if(p->next!=NULL)
p->next->prev = 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 ; 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 <stdio.h>
#include "Dlist.h" void
print(data_t i)
{
printf("数据项为 %d\n", i);
} int main(int argc, char * argv[])
{
DList * plist = NULL;
PNode p = NULL; plist = InitList();
p = InsFirst(plist, MakeNode());
InsBefore(plist, p, MakeNode());
InsAfter(plist, p, MakeNode());
InsAfter(plist, p, MakeNode()); printf("p前驱位置的值为 %d\n", GetData(GetPrev(p)));
printf("p位置的值为 %d\n", GetData(p));
printf("p后继位置的值为 %d\n", GetData(GetNext(p))); printf("遍历输出各节点数据项:\n");
ListTraverse(plist, print); printf("除了头节点该链表共有 %d 个节点\n", GetSize(plist)); FreeNode(DelFirst(plist));
printf("删除了头节点该链表共有 %d 个节点\n", GetSize(plist)); printf("删除第一个节点后重新遍历输出为:\n");
ListTraverse(plist, print); printf("删除了第一个节点后该链表共有 %d 个节点\n", GetSize(plist)); printf("销毁链表...\n");
DestroyList(plist); return ;
}

Demo1:Makefile 文件

CC = gcc
CFLAGS = -g -Wall -o2 RUNE = $(CC) $(CFLAGS) $(object) -o $(exe)
RUNO = $(CC) $(CFLAGS) -c $< -o $@ .RHONY:clean object = test.o Dlist.o
exe = Dlist $(exe):$(object)
$(RUNE) %.o:%.c Dlist.h
$(RUNO)
%.o:%.c
$(RUNO) clean:
-rm -rf *.o Dlist *~~

运行

1.2

double_link.h

#ifndef _DOUBLE_LINK_H_
#define _DOUBLE_LINK_H_ // 节点类型
typedef struct node_t {
struct node_t * prev;
struct node_t * next;
void * data;
}node_t; // 新建 双向循环链表.成功,返回0;否则,返回-1
extern int create_dlink(); // 销毁 双向循环链表.成功,返回0;否则,返回-1
extern int destroy_dlink(); // 双向链表是否为空.为空的话返回1;否则,返回0
extern int dlink_is_empty(); // 返回 双向链表的大小
extern int dlink_size(); // 获取 双向链表中第index位置的元素.成功,返回节点指针;否则,返回NULL
extern void * dlink_get(int index); // 获取 双向链表中第1个元素.成功,返回节点指针;否则,返回NULL
extern void * dlink_get_first(); // 获取 双向链表中最后1个元素.成功,返回节点指针;否则,返回NULL
extern void * dlink_get_last(); // 将value插入到index位置.成功,返回0;否则,返回-1
extern int dlink_insert(int index, void * pval); // 将value插入到表头位置.成功,返回0;否则,返回-1
extern int dlink_insert_first(void * pval); // 将value插入到末尾位置.成功,返回0;否则,返回-1
extern int dlink_append_last(void * pval); // 删除 双向链表中index位置的节点.成功,返回0;否则,返回-1
extern int dlink_delete(int index); // 删除 第一个节点.成功,返回0;否则,返回-1
extern int dlink_delete_first(); // 删除 最后一个节点.成功,返回0;否则,返回-1
extern int dlink_delete_last(); #endif //_DOUBLE_LINK_H_

double_link.c

/*******************
*
* 双向循环链表实现
*
******************/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h> #include "double_link.h" // 表头,不存放元素值
static node_t * phead = NULL; // 节点个数
static int count = ; // 创建节点
static node_t *
create_node(void * pval)
{
node_t * pnode = NULL;
pnode = (node_t *)malloc(sizeof(node_t));
if(NULL == pnode)
return NULL;
// 默认pnode的前一个节点和后一节点都指向它自身
// 双向循环链表,这里不能将pnode->prev = NULL;pnode->next = NULL;
pnode->prev = pnode->next = pnode;
pnode->data = pval; return pnode;
} // 新建 双向循环链表。成功,返回0;否则,返回-1
int
create_dlink()
{
// 创建头
phead = create_node(NULL); // 头节点数据域为NULL
if(!phead)
return -;
// 节点个数为0
count = ; return ;
} // 双向链表是否为空 。为空的话返回1;否则,返回0。
int
dlink_is_empty()
{
if(count == )
return ;
return ;
} // 返回 双向链表的大小
int dlink_size()
{
return count;
} // 获取 双向链表中第 index 位置的节点
static
node_t * get_node(int index)
{
if(index < || index >= count)
return NULL; // 正向查找
if(index <= (count/)) {
int i = ;
node_t * pnode = phead->next;
while((i++)<index)
pnode = pnode->next; return pnode;
} // 反向查找
int j = ;
int rindex = count - index -;
node_t * rnode = phead->prev;
while((j++) < rindex)
rnode = rnode->prev; return rnode;
} // 获取 双向链表中第index位置的元素。成功,返回节点指针;否则,返回NULL。
void * dlink_get(int index)
{
node_t * pindex = get_node(index);
if(!pindex)
return NULL; return pindex->data;
} // 获取 双向链表中第1个元素 。成功,返回节点指针;否则,返回NULL。
void * dlink_get_first()
{
return dlink_get();
} // 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。
void *
dlink_get_last()
{
return dlink_get(count-);
} // 将“value”插入到index位置。成功,返回0;否则,返回-1。
int
dlink_insert(int index, void * pval)
{
// 插入表头
if(index == )
return dlink_insert_first(pval); // 获取插入的位置对应的节点
node_t * pindex = get_node(index);
if(!pindex)
return -; // 创建 节点
node_t * pnode = create_node(pval);
if(!pnode)
return -; pnode->prev = pindex->prev;
pnode->next = pindex;
pindex->prev->next = pnode; // pindex 前一个节点的后继指针指向新节点
pindex->prev = pnode; count++; return ;
} // 将value 插入到表头位置。成功,返回0;否则,返回-1。
int
dlink_insert_first(void * pval)
{
node_t * pnode = create_node(pval);
if(!pnode)
return -; pnode->prev = phead;
pnode->next = phead->next;
phead->next->prev = pnode;
phead->next = pnode; count++; return ;
} // 将value 插入到末尾位置。成功,返回0;否则,返回-1。
int
dlink_append_last(void * pval)
{
node_t * pnode = create_node(pval);
if(!pnode)
return -; pnode->prev= phead->prev;
pnode->next = phead;
phead->prev->next = pnode;
phead->prev = pnode; count++; return ;
} // 删除 双向链表中index位置的节点 。成功,返回0;否则,返回-1
int
dlink_delete(int index)
{
node_t * pindex = get_node(index);
if(!pindex)
return -; pindex->next->prev = pindex->prev;
pindex->prev->next = pindex->next; free(pindex);
count--; return ;
} // 删除第一个节点。成功,返回0;否则,返回-1
int
dlink_delete_first()
{
return dlink_delete();
} // 删除 最后一个节点。成功,返回0;否则,返回-1
int
dlink_delete_last()
{
return dlink_delete(count-);
} // 撤销 双向链表 。成功,返回0;否则,返回-1
int
destroy_dlink()
{
if(!phead)
return -; node_t * pnode = phead->next;
node_t * ptmp = NULL; //遍历节点
while(pnode!=phead) {
ptmp = pnode;
pnode = pnode->next;
free(ptmp);
} free(phead);
phead = NULL; count = ; return ;
}

Makefile 套路走起,(代码临摹别人的,makefile要原创的哦,上下长得一样,俗称 套路)

CC = gcc
CFLAGS = -g -Wall -o2 RUNE = $(CC) $(CFLAGS) $(object) -o $(exe)
RUNO = $(CC) $(CFLAGS) -c $< -o $@ .RHONY:clean object = test.o double_link.o
exe = DlinkLoop $(exe):$(object)
$(RUNE) %.o:%.c double_link.h
$(RUNO)
%.o:%.c
$(RUNO) clean:
-rm -rf *.o DlinkLoop *~~

execute

2. 鸣谢

惯例,感谢二位少侠,Cheers!!!https://blog.csdn.net/zqixiao_09/article/details/50145661
http://www.cnblogs.com/skywang12345/p/3561803.html

3. 后记

九阴真经 - 总纲-2

五脏六腑之精气,皆上注于目而为之精。精之案为眼,骨之精为瞳子,筋之精为络,其案气之精为白眼,

肌肉之为精为约束,裹撷筋骨血气之精而与脉并为系,上属于脑,后出于项中。故邪中与项,因逢其身

之虚,其人深,则随眼系以入于脑,入手面腼则脑转,脑转则引目系急,目系急则目眩以转矣。邪其精

,其精所中不相比亦则精散,精散则视歧,视歧见两物。

阴阳在六,何以言九。太极生两仪,天地初刨判。六阴已机,逢七归元太素,太素西方金德,阴之清纯

,寒值渊源。

内功心法

第一重诀曰:子午卯酉四正时,归气丹田掌前推。面北背南朝天盘,意随两掌行当中。意注丹田一阳动,

左右回收对两穴。拜佛合什当胸作,真气旋转贯其中。气行任督小周天,温养丹田一柱香。快慢合乎三

十六,九阴神功第一重。

注解:每日子、午、卯、酉四正时,找一阴气重的地方,最好为四高中低。面北而坐,五心朝天,静心

绝虑,意守丹田,到一阳初动之时,双手在胸前合什,指尖朝前。引丹田之气沿督脉上行,任脉下归丹

田。如此待小周天三十六圈。由慢至快。气归丹田后,双掌前推,掌心向前,掌指朝天,气行两掌。双

掌指下垂,掌指朝下,掌心朝下,迅速收回,左手掌心对准气海穴,右手掌心对准命门穴,真气随手式

成螺旋状贯入气海、命门两穴。汇于丹田内。如此意守下丹田一柱香的时间。待此功练有一定功力,能

收发自如,有抗寒之功时可修第二重。

Linux C 数据结构->双向链表(阴阳在六,何以言九~)的更多相关文章

  1. Linux内核中双向链表的经典实现

    概要 前面一章"介绍双向链表并给出了C/C++/Java三种实现",本章继续对双向链表进行探讨,介绍的内容是Linux内核中双向链表的经典实现和用法.其中,也会涉及到Linux内核 ...

  2. Linux时间子系统之(十六):clockevent

    专题文档汇总目录 Notes:介绍struct clocke_event_device及其功能feature.模式:触发event接口clockevents_program_event:clockev ...

  3. 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——工作队列

    linux设备驱动归纳总结(六):3.中断的上半部和下半部--工作队列 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  4. kali Linux Web 渗透测试视频教程— 第六课 网络扫描-nmap与zmap

    Kali Linux Web 渗透测试视频教程— 第六课 网络扫描-nmap与zmap 文/玄魂 目录 Kali Linux Web 渗透测试视频教程— 第六课 网络扫描-nmap与zmap. 1 N ...

  5. linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-100005.html linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet x ...

  6. linux设备驱动归纳总结(六):2.分享中断号【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-90837.html xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...

  7. linux设备驱动归纳总结(六):1.中断的实现【转】

    本文转载自:http://blog.chinaunix.net/uid-25014876-id-90740.html linux设备驱动归纳总结(六):1.中断的实现 xxxxxxxxxxxxxxxx ...

  8. SDUT 3345 数据结构实验之二叉树六:哈夫曼编码

    数据结构实验之二叉树六:哈夫曼编码 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 字符的编 ...

  9. linux下Oracle11g RAC搭建(六)

    linux下Oracle11g RAC搭建(六) 五.校验安装前的环境 root身份下完毕解压grid.database安装包 [grid@node1 soft]$ su - Password: [r ...

随机推荐

  1. UVa 12545 比特变换器

    https://vjudge.net/problem/UVA-12545 题意:输入两个等长的串S和T,其中S包含字符0,1,?,但T只包含0和1. 用尽量少的步数把S变成T.每步有3种操作: ①把S ...

  2. Java 面向对象之static,final,匿名对象,内部类,包,修饰符

    01final关键字概念 A: 概述 继承的出现提高了代码的复用性,并方便开发.但随之也有问题,有些类在描述完之后,不想被继承, 或者有些类中的部分方法功能是固定的,不想让子类重写.可是当子类继承了这 ...

  3. Nginx 多重条件判断

    server{ listen 80; server_name xxx.com; index index.html index.htm index.php admin.php; root /home/w ...

  4. ubuntu10.04 交叉编译 aria2 总结

    1) google之后,找到 这个 https://github.com/z24/pitv/tree/master/cross 的脚本, 觉得非常好. 于是准备用来进行编译 2) 安装交叉编译器 su ...

  5. DataGridView1

    for (int i = 0; i < DataGridView1.SelectedRows.Count; i++)    { //第i行第一列 String ai1= DataGridView ...

  6. C#特征备忘

    [assembly:System.CLSCompliant(true)]----利用CLSCompliant属性,可以把程序集标记为与CLS兼容,但仍可以将个别方法的CLSCompliant值设为fa ...

  7. 第五章 [BX]和loop指令

    5.1 [bx] [bx]是什么 和 [0] 有些类似,[0] 表示内存单元,它的偏移地址是 0. 例如: mov ax, [0] 内存以字节为单位:ax以字(16bit = 2Byte)为单位:al ...

  8. JDK1.7 新特性

    1:switch中可以使用字串   String s = "test";   switch (s) {   case "test" :      System. ...

  9. Android 列表使用(ListView GridView Gallery图片计时滚动)

    ListView 作用: 1.将数据填充到布局. 2.处理用户的选择点击等操作. 根据列表的适配器类型,列表分为三种,ArrayAdapter,SimpleAdapter和SimpleCursorAd ...

  10. Jersey 2.x 服务器端应用支持的容器

    基于 JAX-RS Servlet-based 部署的一部分标准,能运行在任何支持 Servlet 2.5 和更高标准的的容器上.Jersey 提供支持程序化部署在下面的容器中:Grizzly 2 ( ...