以下代码都是经验证可执行,具体结果可参考 dl_print 打印信息。
代码里面对过程进行了注释便于理解
#include <stdio.h>
#include <stdlib.h>
//定义双向链表的节点结构
typedef struct Node{
int value;
struct Node *next;
struct Node *prev;
}Double_Node;
//创建双向链表
Double_Node* creat_dblist(int value)
{
Double_Node* head = NULL;
head = (Double_Node*) malloc(sizeof(Double_Node));
if(head == NULL)
printf("creat double list head failed ! \n");
else
{
head->value = value;
head->prev = NULL;
head->next = NULL;//链表的节点是NULL
}
return head;
}
//创建长度为length(算上链表头)的双向链表,value为元素数组 , length为创建双链表长度
Double_Node* creat_length_dblist(int* value ,int length)
{
Double_Node* dl_head = NULL;//创建个链表头
Double_Node *dl_new = NULL;
Double_Node *dl_temp = NULL;
int i ;
dl_head = (Double_Node*)malloc(sizeof(Double_Node));
if(dl_head == NULL)
printf("creat double list head failed ! \n");
else
{
dl_head->value = value[0];
dl_head->prev = NULL;
dl_head->next = NULL;
dl_temp = dl_head;//创建第一个节点,头尾相同
for(i=1;i<length;i++)
{
dl_new = (Double_Node*)malloc(sizeof(Double_Node));
if(dl_new == NULL)
printf("creat double list head failed ! \n");
else
{
//第一次新增的 dl_new_1 的 prev 是 head节点,即 dl_temp,新增节点位于尾部 ,故 next 是NULL
//第二次新增的 dl_new_2 的 prev 是 第一次新增的节点,即 dl_temp( dl_new_1),新增节点位于尾部 next 是NULL
//后面类推。。。
dl_new->value = value[i];
dl_new->prev = dl_temp;
dl_new->next = NULL;
//第一次 dl_temp(dl_new_1) 是头节点,next 指向新增的节点即 dl_new
//第二次 dl_temp(dl_new_2) 是新增的第一个节点,prev节点操作已经执行(dl_new->prev = dl_temp;),此时next 指向新增的 dl_new_2。
//后面类推。。。
dl_temp->next = dl_new;
//进行下一次做准备
dl_temp = dl_new;
}
}
}
return dl_head;
}
//打印链表中的元素 ,传入的是链表头结点
void dl_print(Double_Node* head)
{
while(head)
{
printf("---%d---",head->value);
head = head->next;
}
printf("\n");
}
//双向链表的插入元素操作:后向插入
/*
* 有两种方式:1.传入二级指针,这样可以改变指针本身 2.返回的对象是指针
*/
//传入的参数是链表的头节点以及需要插入的元素
Double_Node* insert_node(Double_Node* head ,int value)
{
Double_Node* temp = head;
Double_Node* new = NULL;
new = (Double_Node*)malloc(sizeof(Double_Node));
new->value = value;
while(temp)
{
if(temp->value > value && temp->next)
{
//可能存在头部 中间
//1.插入在头部
if(temp->prev == NULL)
{
new->prev = NULL;
new->next = temp;
temp->prev = new;
head = new;
break;
}
//2.插入在中间 new tmp
if(temp->next)
{
new->prev = temp->prev;
new->next = temp;
temp->prev->next = new;
temp->prev = new;
break;
}
}
//插在尾部
if(temp->next == NULL)
{
temp->next = new;
new->prev = temp;
new->next = NULL;
break;
}
temp = temp->next;
}
return head;
}
//双向链表的删除节点
Double_Node* del_node(Double_Node* head ,int value)
{
Double_Node* temp = head;
while(temp)
{
if(temp->value == value)
{
//1.删除头节点
if(temp->prev == NULL)
{
head->next->prev = NULL;
head = head->next;
free(temp);
break;
}
//2.删除尾节点
else if(temp->next ==NULL)
{
temp->prev->next = NULL;
free(temp);
break;
}
//3.删除中间节点
else
{
temp->prev->next = temp->next;
temp->next->prev = temp->prev;
free(temp);
break;
}
}
temp = temp->next;
}
return head;
}
//根据指定的位置进行转换链表,如A->B->C->D->E->F 以 C 点 为转换 C->D->E->F->A->B
Double_Node* change_dblist(Double_Node* head ,int value)
{
Double_Node* temp;
Double_Node* tail;
temp = head;
tail = head;
//找到尾节点
while(tail)
{
if(tail->next==NULL)//尾节点
break;
tail = tail->next;
}
while(temp)
{
if(temp->value == value)//说明节点存在
{
//1.翻转节点为头节点
//A->B->C->D->E->F 不变
if(temp->prev == NULL)
{
//无需操作
break;
}
//2.翻转节点为尾节点
//F->A->B->C->D->E
else if(temp->next == NULL)
{
temp->prev->next = NULL;//变成尾节点
head->prev = temp;
temp->next = head;
temp->prev = NULL;
head = temp;
break;
}
//3.翻转节点为中间位置
//C->D->E->F->A->B
else
{
temp->prev->next = NULL;//变成尾节点
//找到尾节点
tail->next = head;
head->prev = tail;
head = temp;
break;
}
}
temp = temp->next;
}
return head;
}
int main()
{
Double_Node* head = NULL;
int length = 10;
int value[10] = {1,3,5,7,9,11,13,15,17,19};
head = creat_length_dblist(value,length);
if(head == NULL)
printf(" creat double list head failed !\n");
else
{
printf(" creat double list head successed !\n");
dl_print(head);
head = insert_node(head,0);
dl_print(head);
head = insert_node(head,4);
dl_print(head);
head = insert_node(head,30);
dl_print(head);
head = del_node(head,0);
dl_print(head);
head = del_node(head,4);
dl_print(head);
head = del_node(head,30);
dl_print(head);
head = change_dblist(head,19);
dl_print(head);
}
}