1双向链表
1.1链表结点结构体定义
c
typedef struct student_data
{
char name[32];
char sex;
int age;
}STU_DATA;
c
typedef struct double_link_node
{
STU_DATA data;//数据域
struct double_link_node *ppre;//指向上一个结点的指针
struct double_link_node *pnext;//指向下一个结点的指针
}DOUB_NODE;
1.2链表头结点结构体定义
c
typedef struct double_link_head
{
DOUB_NODE *phead;//指向首结点的指针
int clen;//记录链表节点数量
}DOUB_HEAD;
1.3双向链表头结点创建
c
/*=============双向链表创建头结点(创建空表)=========*/
void *create_double_link_list_head_node(void)
{
DOUB_HEAD *phead=NULL;
/*创建头结点空间*/
phead=malloc(sizeof(DOUB_HEAD));
if(NULL==phead)
{
perror("fail to malloc");
return NULL;
}
/*头结点初始化*/
phead->phead=NULL;
phead->clen=0;
return phead;
}
1.4双向链表结点创建
c
/*=============双向链表创建新结点==============*/
void* create_double_link_list_new_node(STU_DATA data)
{
DOUB_NODE *pnode=NULL;
/*创建新结点空间*/
pnode=malloc(sizeof(DOUB_NODE));
if(NULL==pnode)
{
perror("fail to malloc");
return NULL;
}
/*新结点初始化*/
pnode->data = data;
pnode->ppre=NULL;
pnode->pnext=NULL;
return pnode;
}
1.5链表非空判断
c
/*=============双向链表非空判断==============*/
int is_empty_link(DOUB_HEAD *list)
{
return NULL==list->phead;
}
1.6双向链表结点插入
1.6.1头插法
c
/*=============双向链表头插法=================*/
int push_head_double_link_list(DOUB_HEAD *list, DOUB_NODE *pnode)
{
if(NULL==list||NULL==pnode)
{
return -1;
}
if(is_empty_link(list))
{
list->phead=pnode;
}
else
{
pnode->pnext=list->phead;//初始化新结点的后继为旧的首结点
list->phead->ppre=pnode;//更新首结点的前驱结点为新结点
list->phead=pnode;//更新头结点的指向为新结点(因为此时新结点为新的首结点)
}
list->clen++;
return 0;
}
1.6.2尾插法
c
/*=============双向链表尾插法=================*/
int push_tail_double_link_list(DOUB_HEAD *list,DOUB_NODE *pnode)
{
DOUB_NODE *ptmp=NULL;
if(NULL==list||NULL==pnode)
{
return -1;
}
if(is_empty_link(list))
{
list->phead=pnode;
}
else
{
/*定义一个遍历指针,初始化为指向首结点*/
ptmp=list->phead;
while(1)
{
if(NULL==ptmp->pnext)
{
break;
}
ptmp=ptmp->pnext;
}
pnode->pnext=ptmp->pnext;//初始化新结点的后继结点为NULL(原来尾结点的指针域)
ptmp->pnext=pnode;//更新尾结点的后继结点为新结点
pnode->ppre=ptmp;//初始化新结点的前继结点为尾结点
}
list->clen++;
return 0;
}
1.7双向链表遍历
1.7.1低配版本遍历
c
/*=============双向链表遍历(原始版)===============*/
int double_list_for_each(DOUB_HEAD *list)
{
DOUB_NODE *ptmp=NULL;
/*判断空表*/
if(is_empty_link(list))
{
return 0;
}
/*初始化遍历指针为指向首结点*/
ptmp=list->phead;
while(1)
{
if(NULL==ptmp)//如果是空表,也满足,如果遍历到链表末尾,也满足条件
{
break;
}
else
{
printf("%-10s\t%-10c\t%-10d\n",ptmp->data.name,ptmp->data.sex,ptmp->data.age);
ptmp=ptmp->pnext;
}
}
return 0;
}
1.7.2指定遍历方法的遍历
c
/*=============双向链表遍历(改进版)===============*/
int double_list_for_each(DOUB_HEAD *list,int dir,void (*pfun)(DOUB_NODE *))
{
return 0;
}
1.8双向链表结点删除
1.8.1头删法
c
bug待改
1.8.2尾删法
c
/*==========双向链表尾删法==========*/
int pop_tail_double_link_list(DOUB_HEAD *list)
{
DOUB_NODE *ptmp=NULL;
if(is_empty_link(list))
{
return 0;
}
ptmp=list->phead;
while(1)
{
if(NULL==ptmp->pnext)
{
break;
}
ptmp=ptmp->pnext;
}
if(ptmp->ppre!=NULL)
{
ptmp->ppre->pnext=NULL;
}
else
{
list->phead=NULL;
}
free(ptmp);
list->clen--;
return 0;
}
1.9双向链表查找
c
1.10双向链表修改
c
1.11双向链表销毁
c
1.12双向链表的其它操作
1.12.1单向链表逆序
c
1.12.2双向链表查找中间结点
c
1.12.3双向链表查找倒数第k个结点
c
1.12.4双向链表删除指定结点
1.12.4.1单结点删除
c
1.12.4.2多结点删除
用于多个结点值相同的情况
c