通过返回值
返回所申请的头结点所在的内存空间首地址
,即创建双向链表
的头结点,代码如下:
示例代码:
node_t *create_dplink_node_1(){
node_t *phead = (node_t *)malloc(sizeof(node_t));
if(NULL == phead){
printf("内存分配失败\n");
exit(-1);
}
phead->data = -1;
phead->front = NULL;
phead->next = NULL;
return phead;
}
内存分配是否成功
;shell命令exit(-1)退出
;前驱、元素、后继
(front、data、next
),而头结点的数据域可以不储存任何数据
,头结点的数据域
在此处,我将其被赋值 -1
;指针域(含前驱、后继)被赋值 NULL
,表示此时的双向链表只有一个头结点
;地址传参
的方法创建双向链表
的头结点,代码如下: int create_dplink_node_2(node_t **phead,int data){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
*phead = (node_t *)malloc(sizeof(node_t));
if(NULL == *phead){
printf("内存分配失败\n");
return -1;
}
(*phead)->data = data;
(*phead)->front = NULL;
(*phead)->next = NULL;
return 0;
}
二级指针变量
,因为二级指针用来存储一级指针变量的地址
,即所申请的双向链表头结点在内存空间的地址
;入参合理性检查
;内存分配是否成功
;数据域(即链表元素)被赋值 -1
;指针域(含前驱、后继)被赋值 NULL
;头结点和第0个结点之间
插入新结点,即头插法
,代码如下: int insert_dplink_list_1(node_t *phead,int data){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
//创建新结点
node_t *pnew = NULL;
create_dplink_node_2(&pnew,data);
//头插到链表
pnew->next = phead->next;
pnew->front = phead;
if(NULL != phead->next)
{
phead->next->front = pnew;
}
phead->next = pnew;
return 0;
}
pnew
;后继指针
(即pnew->next
)指向头结点的后继指针
(phead->next
)此处存储的是第0个结点的地址,可能是空指针(NULL
)即pnew->next = phead->next
;前驱地址
(即pnew->front
)指向头结点的地址,即pnew->front = phead
;phead->next->front = pnew
;phead->next
)指向新结点的地址(pnew
),即phead->next = pnew
;最后一个结点后面插入新结点
,即尾插法
,代码如下: int insert_dplink_list_2(node_t *phead,int data){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
//创建新结点
node_t *pnew = NULL;
create_dplink_node_2(&pnew,data);
//遍历链表,找到最后一个结点
node_t *ptemp = phead;
while(NULL != ptemp->next){
ptemp = ptemp->next;
}
ptemp->next = pnew;
pnew->front = ptemp;
return 0;
}
pnew
;ptemp
;ptemp->next = pnew
;pnew->front = ptemp
; int insert_dplink_list_3(node_t *phead,int pos,int data){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
if(pos < 0){
printf("插入位置不合理,插入失败\n");
return -1;
}
node_t *ptemp = phead;
int i = 0;
for(i = 0; i < pos; i++){
if(NULL == ptemp->next){
break;
}
ptemp = ptemp->next;
}
if(i < pos){
printf("插入位置不合理,插入失败\n");
return -1;
}
//创建新结点
node_t *pnew = NULL;
create_dplink_node_2(&pnew,data);
pnew->next = ptemp->next;
pnew->front = ptemp;
if(NULL != ptemp->next)
{
ptemp->next->front = pnew;
}
ptemp->next = pnew;
return 0;
}
ptemp
;pnew
;头插法插入
即可;头删法
,代码如下: int delete_dplink_list_1(node_t *phead){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
if(NULL == phead->next){
printf("链表只有一个头结点,无其他的结点\n");
return -1;
}
node_t *pdel = phead->next;
if(NULL != pdel->next)
{
pdel->next->front = phead;
}
phead->next = pdel->next;
free(pdel);
pdel = NULL;
return 0;
}
pdel
,并将待删结点的指针
指向头结点的后继结点地址
,即node_t *pdel = phead->next
;待删除结点的下一个结点的前驱指针
指向头结点地址
,即pdel->next->front = phead
;头结点的后继指针
指向待删除结点的下一个结点的地址
,即phead->next = pdel->next
;free(pdel)
;地址赋值NULL
,即pdel = NULL
;尾删法
,代码如下: int delete_dplink_list_2(node_t *phead){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
if(NULL == phead->next){
printf("链表只有一个头结点,无其他的结点\n");
return -1;
}
//遍历链表,找到倒数第二个结点
node_t *ptemp = phead;
while(NULL != ptemp->next->next){
ptemp = ptemp->next;
}
free(ptemp->next);
ptemp->next = NULL;
return 0;
}
while循环
,遍历双向链表,找到倒数第二个结点
,即ptemp
;释放ptemp后继指针,并赋值NULL
,这样就删除了双向链表的尾结点;基本一致
;选择结点在链表中的位置,然后根据链表元素的位置,删除待删结点
,代码如下:
示例代码:
int delete_dplink_list_3(node_t *phead,int pos){
if(NULL == phead){
printf("入参为NULL\n");
return -1;
}
if(NULL == phead->next){
printf("链表只有一个头结点,无其他的结点\n");
return -1;
}
if(pos < 0){
printf("删除位置不合理,删除失败\n");
return -1;
}
node_t *ptemp = phead;
int i = 0;
for(i = 0; i < pos; i++){
ptemp = ptemp->next;
if(NULL == ptemp->next){
break;
}
}
if(i < pos){
printf("删除位置不合理,删除失败\n");
return -1;
}
node_t *pdel = ptemp->next;
if(NULL != pdel->next)
{
pdel->next->front = ptemp;
}
ptemp->next = pdel->next;
free(pdel);
pdel = NULL;
return 0;
}
ptemp
;头删法
即可;单向链表翻转
的思路一致
,都是 将第0个数据结点
后面的所有数据结点
,依次头插
到头结点和第0个数据结点之间
即可,代码如下://翻转
int filp_dplink_list(node_t *phead){
if(NULL == phead){
printf("入参为NULL,请检查..\n");
return -1;
}
if(NULL == phead->next){
printf("只有一个头结点\n");
return -1;
}
if(NULL == phead->next->next){
printf("只有一个数据结点\n");
return -1;
}
node_t *p = phead->next;
node_t *q = p->next;
node_t *ptemp = NULL;
p->next = NULL;
while(NULL != q){
ptemp = q->next;
q->next = phead->next;
q->front = phead;
phead->next->front = q;
phead->next = q;
q = ptemp;
}
return 0;
}
保存指针q的指针域
,即ptemp = q->next
,以便于循环遍历双向链表的所有数据结点
,即每次循环结束前,令q = ptemp,就可以继续向后遍历其他的数据结点
;头插法
的形式,并利用while循环
,将第1个数据结点
及其以后的所有
数据结点依次头插到头结点和第0个数据结点之间
,直到指针q为NULL
,即原双向链表
的第0个结点的指针域为NULL
,就完成了双向链表的所有数据结点的翻转
;本文不再赘述
; https://blog.csdn.net/qq_41878292/article/details/135679744