双向链表与单链表基本上类似,只是在删除和插入时有所不同因为其一个节点中多了一个指向其前驱的头指针,注意在插入和删除一个元素时,通用的插入和删除操作对最后一个元素不起作用,即不能在最后一个元素的后面继续插入元素(能通过尾插法插入),不能删除最后一个元素(能通过查找到最后一个元素,直接将其释放),在双向链表的创建时,若用头插法,需要注意第一个节点元素的插入与后续的节点插入的方法不一样,因为第一个节点元素在插入时并没有后继元素。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义双向链表节点
typedef struct Node
{
struct Node *pre;
int data;
struct Node *next;
} DoubleLinkList;
//双向链表初始化
DoubleLinkList *InitList(DoubleLinkList *DL)
{
DL = (DoubleLinkList *)malloc(sizeof(DoubleLinkList));
if (!DL)
{
exit(-1);
}
memset(DL, 0, sizeof(DoubleLinkList));
DL->pre = NULL;
DL->next = NULL;
return DL;
}
//尾插创建双向链表
DoubleLinkList *CreatDuList(int count)
{
DoubleLinkList *DL;
DoubleLinkList *p;
DoubleLinkList *r;
int i;
int data;
DL = InitList(DL);
r = DL;
for (i = 0; i < count; i++)
{
scanf("%d", &data);
p = (DoubleLinkList *)malloc(sizeof(DoubleLinkList)); //创建节点
if (p == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memset(p, 0, sizeof(DoubleLinkList)); //初始化节点
p->data = data;
p->next = NULL;
r->next = p;
p->pre = r;
r = r->next;
}
return DL;
}
//头插建立双向链表
DoubleLinkList *TopCreatList(int count)
{
DoubleLinkList *p;
DoubleLinkList *r;
DoubleLinkList *DL;
int i;
int data; //保存节点数据域的数值
DL = InitList(DL); //创建头指针
r = DL; //链表的标记指针
//若此时只创建只有一个元素的节点
scanf("%d", &data);
p = (DoubleLinkList *)malloc(sizeof(DoubleLinkList)); //创建节点
if (p == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memset(p, 0, sizeof(DoubleLinkList)); //初始化节点
p->data = data; //填写新建节点的数据域
p->pre = r;
p->next = r->next;
r->next = p;
for (i = 2; i <= count; i++)
{
scanf("%d", &data);
p = (DoubleLinkList *)malloc(sizeof(DoubleLinkList)); //创建节点
if (p == NULL)
{
printf("malloc fail\n");
exit(-1);
}
memset(p, 0, sizeof(DoubleLinkList)); //初始化节点
p->data = data; //填写新建节点的数据域
p->pre = r;
p->next = r->next;
r->next->pre = p;
r->next = p;
}
return DL;
}
//查找双链表元素
void GetListData(DoubleLinkList *DL, int i, int *data)
{
DoubleLinkList *p;
int j;
j = 1;
p = DL->next;
while(p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i)
{
printf("查找错误\n");
exit(-1);
}
*data = p->data;
printf("第 %d 个位置上的值是 %d\n",i, *data);
}
//返回链表的长度
int ListLength(DoubleLinkList *DL)
{
DoubleLinkList *p;
int count;
p = DL->next;
count = 0;
while (p)
{
p = p->next;
count++;
}
return count;
}
//改变单链表元素
void ChangeListData(DoubleLinkList *DL, int i ,int data,int *e)
{
DoubleLinkList *p;
int j;
j = 1;
p = DL->next;
while(p && j < i)
{
p = p->next;
j++;
}
if (!p || j > i)
{
printf("查找错误\n");
exit(-1);
}
*e = p->data; //保存该位置的原始值
p->data = data; //将新值赋给该位置
}
//单链表的插入(不能在末尾的位置插入,即最后一个节点的后面)
void InsertNode(DoubleLinkList *DL, int i, int data)
{
DoubleLinkList *p;
DoubleLinkList *s;
int j;
p = DL;
j = 1;
while (p && j < i) //找到要插入的位置
{
p = p->next;
j++;
}
if (!p || j > i)
{
printf("插入错误\n");
exit(-1);
}
s = (DoubleLinkList *)malloc(sizeof(DoubleLinkList));
s->data = data;
s->pre = p;
s->next = p->next;
p->next->pre = s;
p->next = s;
}
//删除一个元素(不能删除最后一个元素)
void ClearNode(DoubleLinkList *DL, int i, int *data)
{
DoubleLinkList *p;
DoubleLinkList *q;
int j;
p = DL->next;
j = 1;
while (p && j < i) //找到要删除的位置
{
p = p->next;
j++;
}
if (!p || j > i)
{
printf("删除错误\n");
exit(-1);
}
p->pre->next = p->next;
p->next->pre = p->pre;
free(p);
}
//单链表的删除(整表)
void ClearList(DoubleLinkList *DL)
{
DoubleLinkList *p;
DoubleLinkList *q;
p = DL->next; //指向第一个节点
while (p != NULL)
{
q = p->next;
free(p);
p = q;
}
DL->next = NULL; //头结点空
}
//打印链表
void PrintDuList(DoubleLinkList *DL)
{
DoubleLinkList *p;
p = DL->next; //将p设为第一个节点
if (p == NULL)
{
printf("空链表\n");
exit(-1);
}
printf("链表的元素: \n");
while (p != NULL)
{
printf("%d\n", p->data);
p = p->next;
}
}