源代码在博客里可下载,1C币。或者找Q:1286550014要代码
一、导入头文件
#include<stdlib.h>
#include<stdio.h>
二、结构体的定义
//定义一个结构体,用于表示双链表的一个节点
typedef struct node
{
int data; //链表中的数据,此例中我们采用整型
struct node* Next;//本节点指向下一节点的指针
struct node* Prev;//本节点指向前一节点的指针
}D_list,*PD_list;
//定义一个结构体,将双链表的头指针与尾指针放入,方便操作
typedef struct list
{
PD_list pHead;
PD_list pTail;
int length; //用于表示链表长度
}List,*pList;
三、功能函数的定义
本次双链表共有7个函数:
//每次申请节点都要进行相同的操作,为了减少代码的重复书写,我们定义一个函数
//用于申请一个新节点,并将节点的指针返回
PD_list createNode(int data);
//初始化双链表
void initList(pList p);
//在头结点处插入数据
void insertHead(pList p,int data);
//在尾节点出插入新数据
void insertTail(pList p, int data);
//在指定位置插入节点
void insertIndex(pList p, int index);
//删除指定位置出的节点
void deleteIndex(pList p, int index);
//打印整个双链表内的数据
void showList(pList p);
四、功能函数的依次实现
PD_list createNode(int data)
{
PD_list pnew = (PD_list)malloc(sizeof(D_list));//申请空间
pnew->data = data;//以下三句,对新节点进行初始化
pnew->Next = NULL;
pnew->Prev = NULL;
return pnew;//返回新节点指针
}
void initList(pList p)
{
//将头结点和尾节点都赋值为空,长度为0
p->pHead = NULL;
p->pTail = NULL;
p->length = 0;
}
void insertHead(pList p, int data)
{
//申请一个新节点
PD_list pnew = createNode(data);
if (p->pHead == NULL)//如果头结点为空,说明双链表为空,就将头尾都指向新节点
{
p->pHead = pnew;
p->pTail = pnew;
p->length++;
}
else//如果头节点不为空
{
pnew->Next = p->pHead;//先将新节点下一节点指向头结点
p->pHead->Prev = pnew;//再将头结点前一节点指向新节点
p->pHead = pnew;//最后将头结点赋值给新节点,头插法完成
p->length++;
}
}
void insertTail(pList p, int data)
{
PD_list pnew = createNode(data);//创建新节点
if (p->pHead == NULL)//判断双链表是否为空
{
p->pHead = pnew;//为空就讲头尾部节点都指向于新节点
p->pTail = pnew;
p->length++;//长度加1
}
else
{
pnew->Prev = p->pTail;//先将新节点的前指针指向原尾节点
p->pTail->Next = pnew;//再将原尾节点下一节点指针指向于新节点
p->pTail = pnew;//最后将新节点变为尾节点,功能完成
p->length++;//长度加1
}
}
void insertIndex(pList p, int index,int data)
{
PD_list pnew = createNode(data);//申请一个新节点
if (index<0 || index>p->length)//判断下标是否有误
{
printf("对不起,您输入的位置有误,无法插入!");
return;
}
else
{
PD_list ptemp = p->pHead;//定义一个辅助指针,先指向于头部
for (int i = 0; i < index - 1; ++i)//循环遍历到想要插入节点的前一节点
{
ptemp = ptemp->Next;
}
//4步连接
pnew->Next = ptemp->Next;//新节点下一节点指针指向插入位置的下一节点
pnew->Prev = ptemp;//新节点前一指针指向插入位置的前一节点
ptemp->Next->Prev = pnew;//新节点下一节点前指针再指向于新节点
ptemp->Next = pnew;//新节点前节点的下一节点指针指向于新节点
p->length++;//长度加1
}
}
void deleteIndex(pList p, int index)
{
if (index<0 || index>p->length)//判断输入的下标是否有误
{
printf("对不起,您输入的位置有误!\n");
return;
}
else
{
PD_list ptemp = p->pHead;
for (int i = 0; i < index; ++i)//遍历循环到想要删除的下标节点处
{
ptemp = ptemp->Next;
}
//2步完成删除并连接
ptemp->Prev->Next = ptemp->Next;//删除位置前节点下一节点指向于删除位置节点的下一节点
ptemp->Next->Prev = ptemp->Prev;//删除位置的下节点前节点指针指向删除位置的前节点
free(ptemp);//释放掉删除位置处的内存
p->length--;//长度减1
}
}
void showList(pList p)
{
//定义一个辅助指针,用于遍历双链表
PD_list ptemp = p->pHead;
while (ptemp->Next)//循环打印
{
printf("%d->", ptemp->data);
ptemp = ptemp->Next;
}
printf("%d\n", ptemp->data);
printf("双链表长度为:%d\n", p->length);
}
五、双链表的使用(main函数)
以下为我的main函数调用,读者可以根据自己的需求调用不用函数