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(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 = 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 = 0;
Position p = GetHead(plist);
if(i>GetSize(plist) || i<1)
return 0;
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 <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(1));
InsBefore(plist, p, MakeNode(2));
InsAfter(plist, p, MakeNode(3));
InsAfter(plist, p, MakeNode(11));
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 0;
}
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 = 0;
// 创建节点
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 -1;
// 节点个数为0
count = 0;
return 0;
}
// 双向链表是否为空 。为空的话返回1;否则,返回0。
int
dlink_is_empty()
{
if(count == 0)
return 1;
return 0;
}
// 返回 双向链表的大小
int dlink_size()
{
return count;
}
// 获取 双向链表中第 index 位置的节点
static
node_t * get_node(int index)
{
if(index < 0 || index >= count)
return NULL;
// 正向查找
if(index <= (count/2)) {
int i = 0;
node_t * pnode = phead->next;
while((i++)<index)
pnode = pnode->next;
return pnode;
}
// 反向查找
int j = 0;
int rindex = count - index -1;
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(0);
}
// 获取“双向链表中最后1个元素”。成功,返回节点指针;否则,返回NULL。
void *
dlink_get_last()
{
return dlink_get(count-1);
}
// 将“value”插入到index位置。成功,返回0;否则,返回-1。
int
dlink_insert(int index, void * pval)
{
// 插入表头
if(index == 0)
return dlink_insert_first(pval);
// 获取插入的位置对应的节点
node_t * pindex = get_node(index);
if(!pindex)
return -1;
// 创建 节点
node_t * pnode = create_node(pval);
if(!pnode)
return -1;
pnode->prev = pindex->prev;
pnode->next = pindex;
pindex->prev->next = pnode; // pindex 前一个节点的后继指针指向新节点
pindex->prev = pnode;
count++;
return 0;
}
// 将value 插入到表头位置。成功,返回0;否则,返回-1。
int
dlink_insert_first(void * pval)
{
node_t * pnode = create_node(pval);
if(!pnode)
return -1;
pnode->prev = phead;
pnode->next = phead->next;
phead->next->prev = pnode;
phead->next = pnode;
count++;
return 0;
}
// 将value 插入到末尾位置。成功,返回0;否则,返回-1。
int
dlink_append_last(void * pval)
{
node_t * pnode = create_node(pval);
if(!pnode)
return -1;
pnode->prev= phead->prev;
pnode->next = phead;
phead->prev->next = pnode;
phead->prev = pnode;
count++;
return 0;
}
// 删除 双向链表中index位置的节点 。成功,返回0;否则,返回-1
int
dlink_delete(int index)
{
node_t * pindex = get_node(index);
if(!pindex)
return -1;
pindex->next->prev = pindex->prev;
pindex->prev->next = pindex->next;
free(pindex);
count--;
return 0;
}
// 删除第一个节点。成功,返回0;否则,返回-1
int
dlink_delete_first()
{
return dlink_delete(0);
}
// 删除 最后一个节点。成功,返回0;否则,返回-1
int
dlink_delete_last()
{
return dlink_delete(count-1);
}
// 撤销 双向链表 。成功,返回0;否则,返回-1
int
destroy_dlink()
{
if(!phead)
return -1;
node_t * pnode = phead->next;
node_t * ptmp = NULL;
//遍历节点
while(pnode!=phead) {
ptmp = pnode;
pnode = pnode->next;
free(ptmp);
}
free(phead);
phead = NULL;
count = 0;
return 0;
}
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
五脏六腑之精气,皆上注于目而为之精。精之案为眼,骨之精为瞳子,筋之精为络,其案气之精为白眼,
肌肉之为精为约束,裹撷筋骨血气之精而与脉并为系,上属于脑,后出于项中。故邪中与项,因逢其身
之虚,其人深,则随眼系以入于脑,入手面腼则脑转,脑转则引目系急,目系急则目眩以转矣。邪其精
,其精所中不相比亦则精散,精散则视歧,视歧见两物。
阴阳在六,何以言九。太极生两仪,天地初刨判。六阴已机,逢七归元太素,太素西方金德,阴之清纯
,寒值渊源。
内功心法
第一重诀曰:子午卯酉四正时,归气丹田掌前推。面北背南朝天盘,意随两掌行当中。意注丹田一阳动,
左右回收对两穴。拜佛合什当胸作,真气旋转贯其中。气行任督小周天,温养丹田一柱香。快慢合乎三
十六,九阴神功第一重。
注解:每日子、午、卯、酉四正时,找一阴气重的地方,最好为四高中低。面北而坐,五心朝天,静心
绝虑,意守丹田,到一阳初动之时,双手在胸前合什,指尖朝前。引丹田之气沿督脉上行,任脉下归丹
田。如此待小周天三十六圈。由慢至快。气归丹田后,双掌前推,掌心向前,掌指朝天,气行两掌。双
掌指下垂,掌指朝下,掌心朝下,迅速收回,左手掌心对准气海穴,右手掌心对准命门穴,真气随手式
成螺旋状贯入气海、命门两穴。汇于丹田内。如此意守下丹田一柱香的时间。待此功练有一定功力,能
收发自如,有抗寒之功时可修第二重。
来源:oschina
链接:https://my.oschina.net/u/4301507/blog/3877849