概念:
双向链表也叫做双向表,是链表的一种,有多个结点组成,每隔结点都有一个数据域和两个指针域,数据域用来存数据,其中一个指针域用来指向后继结点,另一个指针域指向前驱结点。链表的头结点的数据域不存数据。指向前驱结点的指针域为NULL,指向后驱结点的指针域指向第一个真正存储数据的结点。
下边直接上代码。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FALSE 0
#define TRUE 1
typedef int ElemType;
typedef unsigned int uint;
//双向链表的结点,的结构体
typedef struct DullNode
{
ElemType data;
struct DullNode *per;//指向当前结点的前驱结点的指针
struct DullNode *next;//指向当前节点的后继结点的指
}DullNode,*DuLinkList;//结构体定义类型定义两种类型
//普通结构体类型,和指针型
//带信息结点的双向链表结构体定义
typedef struct infoNode
{
DullNode *head;//指向头结点的指针
DullNode *tail;//指向尾结点的指针
uint len;//链表长度
char *desc;//存储链表的描述信息
}infoNode,*PinfoNode;
/*
* @brief 带信息的双向链表的结构体定义
* @param void
* @return 成功返回TRUE 失败返回FALSE
*
* */
infoNode *List_infrom_Init(void)
{
infoNode *L;
L=(infoNode *)malloc(sizeof(infoNode));
//创建一个头结点
L->head=(DullNode *)malloc(sizeof(DullNode));
L->head->next = NULL;
L->tail=NULL;
L->len = 0;
L->desc=(char *)malloc(32);
strcpy(L->desc,"test list");
return L;
}
/*
* @brief 从头节点链表打印函数
* @param head 双向链表的头指针
* @return 成功返回TRUE 失败返回FALSE
*
* */
void printf_list_from_head(DuLinkList head)
{
if(NULL==head)
{
return;
}
DuLinkList t=head->next;
while (t!=NULL)
{
printf("%d ",t->data);
t=t->next;
}
printf("\n");
}
/*
* @brief 从尾结点链表打印链表
* @param head 双向链表的头指针
* @return 成功返回TRUE 失败返回FALSE
*
* */
void printf_list_from_break(DullNode * pTail)
{
if(NULL==pTail)
{
return ;
}
DullNode * t=pTail;
//一直往前遍历直到遍历到头结点
while (t->per!=NULL)
{
printf("%d ",t->data);
t=t->per;
}
printf("\n");
}
//初始化链表
//可行性
/*
* @brief 初始化双向链表
* @param void
* @return 成功返回TRUE 失败返回FALSE
*
* */
DullNode * Lis_Init(void)
{
//创建一个头结点
DuLinkList head = (DuLinkList)(malloc)(sizeof(DullNode));
head->next=NULL;
head->per=NULL;
//将链表的头指针返回
return head;
}
//双向链表的头插法
/*
* @brief 双向链表头插法
* @param head 双向链表的头指针
* @param pTail 双向链表尾指针地址
* @param data 需要插入的元素的值
* @return 成功返回TRUE 失败返回FALSE
*
* */
int head_insert(DuLinkList head,DullNode ** pTail,ElemType data)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
//创建一个新的结点
DullNode *p=(DullNode *)malloc(sizeof(DullNode));
p->per=NULL;
p->next=NULL;
p->data=data;
//当链表为空的时候第一个被插入的结点就是链表的尾结点。
if(NULL==head->next)
{
* pTail = p;
p->per = head;
head->next=p;
return TRUE;
}
//将新的信号结点的next指向原来链表的第一个数据结点
p->next=head->next;
//将原来链表上的第一个数据结点的前驱指针指向新的结点
head->next->per=p;
//头结点的nest指向新的结点
head->next = p;
//将新的结点的前驱结点指向头结点
p->per=head;
return TRUE;
}
//尾插法
/*
* @brief 双向链表尾插法
* @param head 双向链表的头指针
* @param pTail 双向链表尾指针地址
* @param data 需要插入的元素的值
* @return 成功返回TRUE 失败返回FALSE
*
* */
int Tail_insert(DuLinkList head,DullNode ** pTail,ElemType data)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
//创建一个新的结点
DullNode *p=(DullNode *)malloc(sizeof(DullNode));
p->per=NULL;
p->next=NULL;
p->data=data;
//判断链表是否为空
if(NULL==head->next)
{
head->next = p;
p->per = head;
*pTail = p;
return TRUE;
}
(*pTail)->next=p;//(*pTail)->next不指向NULL指向新的结点
p->per=*pTail;//
*pTail=p;//尾指针指向新的结点
return TRUE;
}
//在指定位置插入结点
/*
* @brief 双向链表尾插法
* @param head 双向链表的头指针
* @param index 指定位置
* @param data 需要插入的元素的值
* @return 成功返回TRUE 失败返回FALSE
*
* */
int insert_by_index(DuLinkList head,uint index,ElemType data)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
//创建一个新的结点
DullNode *p=(DullNode *)malloc(sizeof(DullNode));
p->per=NULL;
p->next=NULL;
p->data=data;
int i=1;
DullNode *t = head->next;//定义临时指针指向第一个结点
while (i<index&&t!=NULL)
{
i++;
t=t->next;//往下轮询
}
if(t==NULL)//调试语句
{
printf("[%s %d] index out of range ...",__FUNCTION__ ,__LINE__);
return FALSE;
}
p->next=t;//新的结点的next指向t,
t->per->next=p;//结点t的前驱结点的next指向新的结点
p->per=t->per;//新的结点的前驱结点指向t的前驱结点
t->per = p;//t的前驱结点指针指向新的结点
}
//在双向链表插入一个节点保持原列表升序
/*
* @brief 双向链表尾插法
* @param head 双向链表的头指针
* @param pTail 双向链表尾指针地址
* @param data 需要插入的元素的值
* @return 成功返回TRUE 失败返回FALSE
*
* */
int ascending_insert(DuLinkList head,DullNode ** pTail,ElemType data)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
//创建一个新的结点
DullNode *p=(DullNode *)malloc(sizeof(DullNode));
p->per=NULL;
p->next=NULL;
p->data=data;
//先判断是否为空
if(NULL==head->next)
{
head->next = p;
p->per=head;
*pTail = p;
return TRUE;
}
DullNode *t = head->next;//定义临时指针指向第一个结点
while (t!=NULL)
{
if(t->data<=data)
{
t=t->next;
continue;
}
p->next=t;//新的结点的next指向t,
t->per->next=p;//结点t的前驱结点的next指向新的结点
p->per=t->per;//新的结点的前驱结点指向t的前驱结点
t->per = p;//t的前驱结点指针指向新的结点
return TRUE;
}
//如果链表遍历完毕,相当于尾插法
(*pTail)->next=p;
p->per=*pTail;
*pTail = p;
/*
* 假如没有尾指针,遍历链表的时候,当遍历到链表的最后一个结点的时候就要停止遍历
* */
return TRUE;
}
//删除链表上的指定位置的结点
/*
* @brief 双向链表尾插法
* @param head 双向链表的头指针
* @param index 指定位置
* @return 成功返回TRUE 失败返回FALSE
*
* */
int Delete_node(DuLinkList head,uint index)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
DullNode *t = head->next;//定义临时指针指向第一个结点
int i=1;
while (i<index&&t!=NULL)
{
i++;
t=t->next;
}
//先判断是否超范围
if(NULL==t)
{
printf("[%s %d] index out of range ...",__FUNCTION__ ,__LINE__);
return FALSE;
}
t->per->next=t->next;
t->next->per=t->per;
free(t);
return TRUE;
}
//删除链表的指定元素
/*
* @brief 双向链表尾插法
* @param head 双向链表的头指针
* * @param data 指定元素值
* @return 成功返回TRUE 失败返回FALSE
*
* */
int Delete_Value(DuLinkList head,ElemType data)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
DullNode *t = head->next;//定义临时指针指向第一个结点
//先判断是否超范围
if(NULL==t)
{
printf("[%s %d] index out of range ...",__FUNCTION__ ,__LINE__);
return FALSE;
}
while (t!=NULL)
{
if(t->data == data)
{
t->per->next=t->next;
t->next->per=t->per;
free(t);//释放链表空间
}
t=t->next;
}
return TRUE;
}
/*
* @brief 销毁链表
* @param head 双向链表头指针
* @param pTail 双向链表尾指针地址
* @return 成功返回TRUE 失败返回FALSE
*/
int Destroy_list(DuLinkList head,DullNode **pTail)
{
if(NULL==head)
{
printf("[%s %d] head point is NULL",__FUNCTION__ ,__LINE__);
return FALSE;
}
DullNode * t=head->next;//定义临时指针指向第一个结点
while (t->next!=NULL)
{
head->next=t->next;
t->next->per=head;
free(t);
t=head->next;
}
head->next=NULL;
free(t);//释放最后一个结点
free(head);//释放头结点
*pTail=NULL;//防止尾指针成为野指针
printf("The linked list was destroyed successfully");
return TRUE;
}
int main() {
printf("Hello, World!\n");
DuLinkList head=Lis_Init();
DullNode *tail = NULL;//尾指针
int i;
//验证头插法
for(i=0;i<10;i++)
{
head_insert(head,&tail,100+i);
}
//打印
printf_list_from_head(head);
printf_list_from_break(tail);
//验证尾插法
for(i=0;i<10;i++)
{
Tail_insert(head,&tail,100+i);
}
//打印
printf_list_from_head(head);
//验证指定位置插入节点
insert_by_index(head,2,1000);
//打印
printf_list_from_head(head);
//删除链表上的指定位置的结点
Delete_node( head,1);
printf_list_from_head(head);
//删除链表上的指定元素
Delete_Value(head,100);
printf_list_from_head(head);
//销毁链表
Destroy_list(head,&tail);
return 0;
}