【概念】
需要明白定位、插入、和删除在严版教材中的含义。
定位是指找到第i个结点(Y29,利用指针和循环变量同步变化的特性找第i个结点),插入是指在第i个结点之前插入,删除是指删除第i个结点
【创建】
//尾插法创建循环双链表
DLNode* CreateDList(int a[], int n)
{
//创建头结点
DLNode* L = (DLNode*)malloc(sizeof(DLNode));
L->next = L->prior = L;
//构建尾指针
DLNode *r;
r = L;
//循环插入结点
DLNode*s;
int i;
for (i = 0; i < n; ++i)
{
s = (DLNode*)malloc(sizeof(DLNode));
s->data = a[i];
//在头结点和尾结点之间插入一个新结点
r->next->prior = s;
s->next = r->next;
r->next = s;
s->prior = r;
//尾指针指向新结点
r = s;
}
return L;
}
测试结果:
【定位】
//以下为曾经的理解,最新解释应当是查找第i个结点的位置,不是查找某一个值
//定位,返回查找值x在链表中的位置i,设头结点位置为0
//若x在表内则返回实际位置,若不在则返回尾结点位置
int Locate(DLNode* L, int x)
{
int i;
DLNode* p;
p = L;
i = 0;
while (p->next != L)//最新理解:假设x表示位置,p为L->next,j = 0,则条件为p != L && j < i
{
++i;
if (p->next->data == x)
{
break;
}
p = p->next;
}
return i;
}
测试结果:
【插入】
//在第index位置后插入x,例如3后面插入6
void Insert(DLNode*L, int x, int index)
{
int i;
DLNode* r = L, *s;
for (i = 0; i < index; ++i)
{
r = r->next;//p每移动一次,i就加1
}
//尾插法插入到r之后
s = (DLNode*)malloc(sizeof(DLNode));
s->data = x;
//在头结点和尾结点之间插入一个新结点
r->next->prior = s;
s->next = r->next;
r->next = s;
s->prior = r;
}
测试结果:
【删除】
//删除值为x的结点
void Delete(DLNode*L, int x)
{
DLNode* pre,*p;
p = L->next;
//找到该结点
while (p != L)
{
if (p->data == x)
break;
p = p->next;
}
//若x在表内才删除结点
if (p != L)
{
pre = p->prior;
p->next->prior = pre;
pre->next = p->next;
free(p);
}
}
测试结果:
如图所示,值为6的结点已被删除
【完整代码】
#include <stdio.h>
#include <stdlib.h>
#define maxSize 100
typedef struct DLNode
{
int data;
struct DLNode* prior;
struct DLNode* next;
}DLNode;
//尾插法创建循环双链表
DLNode* CreateDList(int a[], int n)
{
//创建头结点
DLNode* L = (DLNode*)malloc(sizeof(DLNode));
L->next = L->prior = L;
//构建尾指针
DLNode *r;
r = L;
//循环插入结点
DLNode*s;
int i;
for (i = 0; i < n; ++i)
{
s = (DLNode*)malloc(sizeof(DLNode));
s->data = a[i];
//在头结点和尾结点之间插入一个新结点
r->next->prior = s;
s->next = r->next;
r->next = s;
s->prior = r;
//尾指针指向新结点
r = s;
}
return L;
}
//定位,返回查找值x在链表中的位置i,设头结点位置为0
//若x在表内则返回实际位置,若不在则返回尾结点位置
int Locate(DLNode* L, int x)
{
int i;
DLNode* p;
p = L;
i = 0;
while (p->next != L)
{
++i;
if (p->next->data == x)
{
break;
}
p = p->next;
}
return i;
}
//在第index位置后插入x,例如3后面插入6
void Insert(DLNode*L, int x, int index)
{
int i;
DLNode* r = L, *s;
for (i = 0; i < index; ++i)
{
r = r->next;//p每移动一次,i就加1
}
//尾插法插入到r之后
s = (DLNode*)malloc(sizeof(DLNode));
s->data = x;
//在头结点和尾结点之间插入一个新结点
r->next->prior = s;
s->next = r->next;
r->next = s;
s->prior = r;
}
//删除值为x的结点
void Delete(DLNode*L, int x)
{
DLNode* pre,*p;
p = L->next;
//找到该结点
while (p != L)
{
if (p->data == x)
break;
p = p->next;
}
//若x在表内才删除结点
if (p != L)
{
pre = p->prior;
p->next->prior = pre;
pre->next = p->next;
free(p);
}
}
int main()
{
int a[maxSize] = { 1,2,3,4,5 };
int n = 5;
//双向循环链表的创建,定位,插入和删除
DLNode* L = CreateDList(a, n);
int i = Locate(L, 3);
Insert(L, 6, i);
Delete(L, 6);
return 0;
}