基础要义
双向链表的节点结构
双向链表的插入
要先把插入位置的后继节点重新绑定,否则容易丢失后继节点
双向链表的删除
同样是先绑定后继节点
C++代码
#include "stdio.h"
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXSIZE 20 /* 存储空间初始分配量 */
typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
typedef int ElemType;/* ElemType类型根据实际情况而定,这里假设为int */
Status visit(ElemType c)
{
printf("%d ", c);
return OK;
}
typedef struct DulNode
{
ElemType data;
struct DulNode* prior;//前驱
struct DulNode* next; //后继
}DulNode, *DuLinkList;
Status InitList(DuLinkList* L)
{
*L = new DulNode();
if (!(*L)) //存储分配失败
return ERROR;
//前驱 后继都是自己
(*L)->next = (*L);
(*L)->prior = (*L);
}
//判断链表是否为空
const Status ListEmpty(DuLinkList *L)
{
if ((*L)->next == (*L))
return TRUE;
return ERROR;
}
//将L重置为空表
Status ClearList(DuLinkList* L)
{
DuLinkList p;
DuLinkList q;
p = (*L)->next;
while (p != (*L))
{
q = p->next;
delete p;
p = q;
}
(*L)->next = (*L);
return OK;
}
//返回L中的元素个数
const int ListLength(DuLinkList* L)
{
int i = 0;
DuLinkList p = (*L)->next;
while (p != (*L))
{
i++;
p = p->next;
}
return i;
}
// 用e返回L中第i个元素的值
Status GetElem(DuLinkList* L, int i, ElemType* e)
{
int j = 1;
DuLinkList p;
p = (*L)->next;
while ((p != (*L)) && j < i)
{
p = p->next;
j++;
}
if ((p == (*L)) || j > i)
return ERROR;
*e = p->data;
return OK;
}
// 寻找第 1个 与e满足关系的数据元素的位置
int LocateElem(DuLinkList* L, ElemType e)
{
int i = 0;
DuLinkList p = (*L)->next;
while (p != (*L))
{
i++;
if (p->data == e)
return i;
p = p->next;
}
return 0; //没有这个元素
}
//在第i个位置中插入新的数据元素
Status ListInsert(DuLinkList* L, int i, ElemType e)
{
DuLinkList N = new DulNode();
N->data = e;
int j = 1;
DuLinkList p = *L;
//要找到待插入节点的前驱
while ((j < i) && (p->next != (*L)))
{
p = p->next;
j++;
}
//没有这么长的链表
if ((j < i) && (p == (*L)))
return ERROR; // 没有这么长的表
//插入操作
N->next = p->next;
N->next->prior = N;
N->prior = p;
p->next = N;
}
//删除L的第i个元素 并用e返回其值
Status ListDelete(DuLinkList* L, int i, ElemType* e)
{
int j = 1;
DuLinkList p = (*L);
DuLinkList q;
while ((p->next != (*L)) && (j < i))
{
p = p->next;
j++;
}
if (p->next == (*L))
return ERROR;
*e = p->next->data; //取出将要删除的元素的值
//更新要删除的元素的前驱元素的后继,以及后继元素的前驱
q = p->next;
p->next = p->next->next;
p->next->prior = p;
delete q;
return OK;
}
//依次输出L的每个数据元素
const Status ListTraverse(DuLinkList* L)
{
DuLinkList p = (*L)->next;
while (p != (*L))
{
visit(p->data);
p = p->next;
}
printf("\n");
return OK;
}
//随机产生n个元素的值,建立带表头节点的单链线性表 L(尾插法)
void CreateListTail(DuLinkList* L, int n)
{
//生成1-10 数字并且存入到链表中
DuLinkList p = *L;
for (int i = 0; i < n; i++)
{
DuLinkList N = new DulNode();
N->data = i;
p->next = N; //将新的数据加入到尾巴
N->prior = p;
p = p->next; //当前指针往后走一步
p->next = *L; //表示当前链表结束
}
}
//随机产生n个元素的值,建立带表头节点的单链线性表 L(头插法)
void CreateListHead(DuLinkList* L, int n)
{
//生成1-10 数字并且存入到链表中
DuLinkList p = (*L)->next;
for (int i = 0; i < n; i++)
{
DulNode* N = new DulNode();
N->data = i;
N->next = p; //将第一个指针放到后面
p->prior = N;
(*L)->next = N; //新的第一个元素
N->prior = (*L);
p = N; //表头指针
}
}
//获得元素e的前驱元素
const ElemType GetElemIPrior(DuLinkList* L, ElemType e)
{
int j = 1;
DuLinkList p = (*L);
while ((p->next != (*L)))
{
if (p->next->data == e)
return p->next->prior->data; //这一步操作只是验证
p = p->next;
}
return ERROR;
}
int main()
{
DuLinkList L = NULL;
ElemType e;
Status i;
int j;
int k;
i = InitList(&L);
printf("初始化后:ListLength(L) = %d \n", ListLength(&L));
for (int j = 1; j <= 5; j++)
{
int i = ListInsert(&L, 1, j);
}
printf("在L的表头依次插入1~5后:ListLength(L) = %d \n", ListLength(&L));
ListTraverse(&L);
printf("ListLength(L)=%d \n", ListLength(&L));
i = ListEmpty(&L);
printf("L是否空:i=%d(1:是 0:否)\n", i);
i = ClearList(&L);
printf("清空L后:ListLength(L)=%d\n", ListLength(&L));
i = ListEmpty(&L);
printf("L是否空:i=%d(1:是 0:否)\n", i);
for (int j = 1; j <= 10; j++)
ListInsert(&L, j, j);
printf("在L的表尾依次插入1~10后:L.data=");
ListTraverse(&L);
printf("ListLength(L)=%d \n", ListLength(&L));
ListInsert(&L, 1, 0);
printf("在L的表头插入0后:L.data=");
ListTraverse(&L);
printf("ListLength(L)=%d \n", ListLength(&L));
GetElem(&L, 5, &e);
printf("第5个元素的值为:%d\n", e);
for (int j = 3; j <= 4; j++)
{
k = LocateElem(&L, j);
if (k)
printf("第%d个元素的值为%d\n", k, j);
else
printf("没有值为%d的元素\n", j);
}
for (int j = 3; j <= 4; j++)
{
k = LocateElem(&L, j);
if (k)
printf("第%d个元素的值为%d\n", k, j);
else
printf("没有值为%d的元素\n", j);
}
k = ListLength(&L); /* k为表长 */
for (int j = k + 1; j >= k; j--)
{
i = ListDelete(&L, j, &e); /* 删除第j个数据 */
if (i == ERROR)
printf("删除第%d个数据失败\n", j);
else
printf("删除第%d个的元素值为:%d\n", j, e);
}
printf("依次输出L的元素:");
ListTraverse(&L);
j = 5;
ListDelete(&L, j, &e); /* 删除第5个数据 */
printf("删除第%d个的元素值为:%d\n", j, e);
printf("依次输出L的元素:");
ListTraverse(&L);
i = ClearList(&L);
printf("\n清空L后:ListLength(L)=%d\n", ListLength(&L));
CreateListHead(&L, 20);
printf("整体创建L的元素(头插法):");
ListTraverse(&L);
i = ClearList(&L);
printf("\n删除L后:ListLength(L)=%d\n", ListLength(&L));
CreateListTail(&L, 20);
printf("整体创建L的元素(尾插法):");
ListTraverse(&L);
ElemType ee = GetElemIPrior(&L, 5);
printf("元素5的前驱是%d \n:", ee);
}