您的位置:首页 > 理论基础 > 数据结构算法

算法与数据结构之四----双向链表

2014-01-04 19:57 411 查看
/****************************************************************

文件内容:线性表之循环链表操作

版本V1.0

说明:单链表必需从头结点开始遍历,而双链表可以可以往前后两个方向都可以遍历

1.赋值和指向方向不能搞错 A 赋值给B ,说明B指向A

2.双向链表跟普通链表操作思想一样,只不过多了一个前驱指针而已。

思路完全一致。

作者:HFL

时间:2013-12-29

*****************************************************************/

#include<stdio.h>

#include<malloc.h>

#include <windows.h>

//#define RELEASE_VERSION //release版本开关

//#define TRIDiTION

/*inlude<malloc.h> stdlib.h 包含malloc.h*/

#ifdef RELEASE_VERSION

#define Log

#else

#define Log printf

#endif

/*为了提高程序的可移植性,千万不能使用裸露的数据类型*/

#ifndef UINT32

typedef unsigned int UINT32 ;

#endif

#ifndef INT32

typedef int INT32 ;

#endif

typedef struct DNode

{

INT32 data;

struct DNode *prior,*next;

}Dnode,*Linklist;

/****************************************************************

函数功能:创建一个节点

输入参数: 无

返回值:节点的指针

作者:HFL

时间:2013-12-22

*****************************************************************/

Linklist Creat_DNode(INT32 X)

{

Linklist s;

s=(struct DNode *)malloc(sizeof(DNode));

if(NULL==s)

{

Log(" sorry,Malloc is failed\n");

}

else

{

Log(" Malloc is successed!\n");

s->data = X;

}

return s;

}

/****************************************************************

函数功能:初始化链表1(即头部创建一个链表)

输入参数: 无

返回值:链表的标头指针

作者:HFL

时间:2013-12-29

*****************************************************************/

Linklist Head_Creat_Linklist()

{

Linklist L=NULL;

DNode *s;

INT32 x;

scanf("%d",&x);

while(x!=0)

{

s=(struct DNode *)malloc(sizeof(DNode));

if(NULL==s)

{

Log(" sorry,Malloc is failed\n");

}

else

{

Log(" Malloc is successed!\n");

s->next = L;

s->data = x ;

if ( NULL != L)

{

L->prior = s; /*第一个节点再没有后面的节点了*/

}

L = s;

s->prior = L;

scanf("%d",&x);

}

}

return L;

}

/****************************************************************

函数功能:初始化链表2(即尾部创建一个链表)

输入参数: 无

返回值:链表的标头指针

说明:要引入一个新的指针变量,用于链接前后节点

作者:HFL

时间:2013-12-22

************T*****************************************************/

Linklist Tail_Creat_DLinklist()

{

Linklist L=NULL;

DNode *s;

DNode *probe =NULL;

INT32 x;

scanf("%d",&x);

while(x!=0)

{

s=(struct DNode *)malloc(sizeof(DNode));

if(NULL==s)

{

Log(" sorry,Malloc is failed\n");

}

else

{

Log(" Malloc is successed!\n");

if(L== NULL)

{

L = s; //第一个节点地址就必需保存到头节点

s->prior = L ;

}

else

{

probe->next = s; //第二个节点开始,要引入一个临时指针,来暂存上一个节点地址,一遍链接前后两个节点

s->prior = probe;

}

probe = s; //每次创建一个新节点,节点都必需重新移动。

s->data = x ;

s->next = NULL;

scanf("%d",&x);

}

}

return L;

}

/****************************************************************

函数功能:从前往后遍历整个链表

输入参数: 链表头指针

返回值:无

说明:遍历不能影响原来链表的结构。

作者:HFL

时间:2013-12-22

************T*****************************************************/

void List_Back_Linklist(Linklist L)

{

Linklist temp = L;//不能使用L指针,否则将链表头指针移动,链表被破坏,故使用一个临时指针来变量

INT32 i = 0;

if (NULL == L)

{

return ;

}

while(NULL!=temp)

{

printf("the data[%d]=%d\n",++i,temp->data);

//L->next=L->next->next;

temp = temp->next;

}

return ;

}

/****************************************************************

函数功能:从后往前遍历整个链表

输入参数: 链表头指针

返回值:无

说明:遍历不能影响原来链表的结构。

作者:HFL

时间:2013-12-29

************T*****************************************************/

void List_Head_Linklist(Linklist L,Linklist p)

{

Linklist temp = p;//不能使用L指针,否则将链表头指针移动,链表被破坏,故使用一个临时指针来变量

INT32 i = 0;

if ( NULL == p )

{

return ;

}

while(L != temp)

{

printf("the data[%d]=%d\n",++i,temp->data);

//L->next=L->next->next;

temp = temp->prior;

}

printf("list the data[%d]=%d\n",++i,temp->data);

return ;

}

/****************************************************************

函数功能:按位置查找

输入参数: 链表头指针和位置i

返回值: 节点指针,如果无NULL,说明没有找到,否则说明找到,为temp指针指向的节点

说明:查找不能影响原来链表的结构。

作者:HFL

时间:2013-12-29

************T*****************************************************/

Linklist Search_Position_Linklist(Linklist L,INT32 i)

{

Linklist temp = L;//不能使用L指针,否则将链表头指针移动,链表被破坏,故使用一个临时指针来变量

INT32 position = 1;

while(NULL != temp && position != i)

{

temp = temp->next;

position++;

}

if (position < i)

{

printf("can't finded the postion!\n");

return NULL;

}

return temp;

}

/****************************************************************

函数功能:按值查找

输入参数: 链表头指针和位置i

返回值: 节点指针,如果为NULL,说明没有找到,否则说明找到,为temp指针指向的节点

说明:查找不能影响原来链表的结构。

作者:HFL

时间:2013-12-29

************T*****************************************************/

Linklist Search_Value_Linklist(Linklist L,INT32 X)

{

Linklist temp = L;//不能使用L指针,否则将链表头指针移动,链表被破坏,故使用一个临时指针来变量

INT32 position = 1;

while(NULL != temp && temp->data != X)

{

temp = temp->next;

position++;

}

if(temp == L && temp->data != X )

{

Log ("sorry ,can't finded the data\n");

}

else

{

Log("The data is finded at positon[%d]\n",position);

}

return temp;

}

/****************************************************************

函数功能:从p节点按值向前查找

输入参数: 链表头指针和位置i

返回值: 节点指针,如果为NULL,说明没有找到,否则说明找到,为temp指针指向的节点

说明:查找不能影响原来链表的结构。

作者:HFL

时间:2013-12-29

************T*****************************************************/

Linklist Search_Before_Value_Linklist(Linklist L,INT32 X,Linklist p)

{

Linklist temp = p;//不能使用L指针,否则将链表头指针移动,链表被破坏,故使用一个临时指针来变量

INT32 position = 0;

if ( NULL == p )

{

return NULL;

}

while(L != temp && temp->data != X)

{

temp = temp->prior;

position++;

// Log ("hello\n");

}

if(temp == L && temp->data != X )

{

Log ("sorry ,can't finded the data\n");

}

else

{

Log("The data is finded at back positon[%d]\n",position);

}

return temp;

}

/****************************************************************

函数功能: 从P节点后面插入k节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 插入会改变节点的结构,如果是头节点插入,会修改头节点的。

作者:HFL

时间:2013-12-29

****************************************************************/

Linklist Insert_Back_DLinklist(Linklist L, Linklist p,Linklist k)

{

if(NULL == L || NULL== k || NULL==p)

{

Log (" The linklist is null\n");

return NULL;

}

k->next=p->next;

p->next->prior= k;

p->next=k;

k->prior = p;

return L;

}

/****************************************************************

函数功能: 从P节点前面插入k节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 插入会改变节点的结构,如果是头节点插入,会修改头节点的。

前面插入要找前驱,效率低,一般使用双向链表,直接使用前驱指针

作者: HFL

时间:2013-12-29

****************************************************************/

Linklist Insert_Front_DLinklist(Linklist L, Linklist p,Linklist k)

{

Linklist temp = L;

if(NULL == L || NULL== k || NULL==p)

{

Log (" The linklist is null\n");

return NULL;

}

k->next = p;

k->prior = p->prior; /*顺序不能改,要先操作新节点,再操作老节点*/

p->prior->next = k;

p->prior = k;

return L;

}

/****************************************************************

函数功能: 从第i节点位置插入值为X的节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 先找到i-1节点,然后在i-1节点后找出入一个节点,即i 位置的节点。

与单链表一样,只是底层实现不一样而已。

作者:HFL

时间:2013-12-29

****************************************************************/

Linklist Insert_i_Linklist(Linklist L,INT32 i,INT32 X)

{

Linklist temp = Search_Position_Linklist(L,i-1);

Linklist s = Creat_DNode(X);

if(!Insert_Back_DLinklist(L,temp,s))

{

Log(" Insert back of p node is failed \n");

return NULL ;

}

return L;

}

/****************************************************************

函数功能: 从P节点后面删除一个节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 插入会改变节点的结构,如果是头节点插入,会修改头节点的。

作者:HFL

时间:2013-12-2

****************************************************************/

Linklist Delete_Back_Linklist(Linklist L, Linklist p )

{

Linklist s;//删除后面的节点s

if(NULL == L || NULL== p)

{

Log (" The linklist is null\n");

return NULL;

}

s = p->next;

p->next = s->next;

s->next->prior = p; //指针可以一路连续指下去,但为了不出错,中间节点还是用s来保存

free(s);//注意是释放p 节点后面的节点,而不是p节点

return L;

}

/****************************************************************

函数功能: 从P节点前面删除s节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 插入会改变节点的结构,如果是头节点插入,会修改头节点的。

前面插入要找前驱,效率低,一般使用双向链表,直接使用前驱指针

作者: HFL

时间:2013-12-29

****************************************************************/

Linklist Delete_Front_Linklist(Linklist L, Linklist p)

{

Linklist s;

if(NULL == L || NULL==p)

{

Log (" The linklist is null\n");

return NULL;

}

s = p->prior;

s->prior->next = p;

p->prior = s->prior;

free (s);
//释放I节点前的一个节点

return L;

}

/****************************************************************

函数功能: 删除第i节点

输入参数: 链表头指针和p节点位置

返回值: 头节点

说明: 先找到i-1节点,然后在i-1节点后找出入一个节点,即i 位置的节点。

作者:HFL

时间:2013-12-29

****************************************************************/

Linklist Delete_i_Linklist(Linklist L,INT32 i)

{

Linklist temp = Search_Position_Linklist(L,i-1);

if(!Delete_Back_Linklist(L,temp))

{

Log(" Insert back of p node is failde \n");

return NULL ;

}

return L;

}

void main()

{

Linklist L,temp;

Log("*******************************\n");

Log("* *\n");

Log("* Creat DLinklist is start ! *\n");

Log("* *\n");

Log("*******************************\n");

L = Tail_Creat_DLinklist();

//L = Head_Creat_Linklist();

if(!L)

{

Log(" the Creat Linklist is failed\n");

}

else

{

Log(" the Creat Linklist is secuseed\n");

}

Log("*************************************\n");

Log("* *\n");

Log("* Back List DLinklist is start ! *\n");

Log("* *\n");

Log("*************************************\n");

List_Back_Linklist(L);

Log("*************************************\n");

Log("* *\n");

Log("* Head List DLinklist is start ! *\n");

Log("* *\n");

Log("*************************************\n");

// List_Head_Linklist(L,Search_Position_Linklist(L,5));

List_Head_Linklist(L,Search_Before_Value_Linklist(L,12,Search_Position_Linklist(L,5)));

Insert_Back_DLinklist(L,Search_Position_Linklist(L,5),Creat_DNode(1000));

Log("*************************************************\n");

Log("* *\n");

Log("* Insert P Node In DLinklist back is start ! *\n");

Log("* *\n");

Log("*************************************************\n");

List_Back_Linklist(L);

Log("*************************************************\n");

Log("* *\n");

Log("* Insert P Node In DLinklist front is start ! *\n");

Log("* *\n");

Log("**************************************************\n");

Insert_Front_DLinklist(L,Search_Position_Linklist(L,5),Creat_DNode(999));

List_Back_Linklist(L);

Log("*************************************************\n");

Log("* *\n");

Log("* Insert I Node In DLinklist front is start ! *\n");

Log("* *\n");

Log("**************************************************\n");

Insert_i_Linklist(L,5,2222);

List_Back_Linklist(L);

Log("*************************************************\n");

Log("* *\n");

Log("* Delete P Node In DLinklist back is start ! *\n");

Log("* *\n");

Log("**************************************************\n");

Delete_Back_Linklist(L,Search_Position_Linklist(L,5));

List_Back_Linklist(L);

Log("*************************************************\n");

Log("* *\n");

Log("* Delete P Node In DLinklist front is start ! *\n");

Log("* *\n");

Log("**************************************************\n");

Delete_Front_Linklist(L,Search_Position_Linklist(L,5));

List_Back_Linklist(L);

Log("*************************************************\n");

Log("* *\n");

Log("* Delete P Node In DLinklist is start ! *\n");

Log("* *\n");

Log("**************************************************\n");

Delete_i_Linklist(L,5);

List_Back_Linklist(L);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: