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. Yandex.Algorithm 2011 Round 2 D. Powerful array 莫队

    题目链接:点击传送 D. Powerful array time limit per test 5 seconds memory limit per test 256 megabytes input ...

  2. 51nod 1232 完美数 数位dp

    1232 完美数 题目来源: 胡仁东 基准时间限制:2 秒 空间限制:131072 KB  如果一个数能够被组成它的各个非0数字整除,则称它是完美数.例如:1-9都是完美数,10,11,12,101都 ...

  3. hdu 1573 X问题 两两可能不互质的中国剩余定理

    X问题 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Desc ...

  4. Java 中时间处理 System.currentTimeMillis()

    import org.testng.annotations.Test;import java.text.ParseException;import java.text.SimpleDateFormat ...

  5. 【转】xml节点解析成字符串的方法

    网址:http://blog.csdn.net/shanzhizi/article/details/8817532 ZC: 这是 libxml2的 之前汇总了一篇关于xml文档与字符串转换的文章,文章 ...

  6. Mask R-CNN论文理解

    摘要: Mask RCNN可以看做是一个通用实例分割架构. Mask RCNN以Faster RCNN原型,增加了一个分支用于分割任务. Mask RCNN比Faster RCNN速度慢一些,达到了5 ...

  7. 创意时钟 人形时钟 可惜不是 https

    ; (function () { $('#header').css({ 'position':'relative' }).prepend('<div id="clockWrap&quo ...

  8. Python 爬虫-图片的爬取

    2017-07-25 22:49:21 import requests import os url = 'https://wallpapers.wallhaven.cc/wallpapers/full ...

  9. Java实例-坦克大战

    Java实例-坦克大战 一.样例图片 二.类图结构 坦克大战中的所有类 类的关系图 我的坦克类 三.说明 1.每一个新的独立运行的东西就是一个线程,像我方坦克,像敌方坦克,像所有的子弹 2.每一个线程 ...

  10. java反射究竟消耗多少效率

    原文出处 一直以来都对Java反射究竟消耗了多少效率很感兴趣,今晚总算有空进行了一下测试 测试被调用的类和方法 package com.spring.scran; public class TestM ...