循环链表.docx
《循环链表.docx》由会员分享,可在线阅读,更多相关《循环链表.docx(15页珍藏版)》请在冰豆网上搜索。
循环链表
1.1循环链表
一、循环链表的建立与释放
循环链表也就是将链表的尾端指针指向首节点。
P320
1、首先我们将说明循环链表的建立。
建立循环链表的方式和建立单链表类似,只不过单链表的最后一个节点指向NULL,而循环链表的最后一个节点是指向首节点上。
我们以建立单链表的例如子介绍环状列表。
现在有3个节点如下:
P320
我们现在想要把3个节点依次给串连成循环链表,则运作过程如下:
Head=Node_1;
Node_1->Next=Node_2;
Node_2->Next=Node_3;
Node_3->Next=Head;
在循环链表的释放,如果采用和单链表相同的释放方式,会发生不知是否已到达最后一个节点的错误,如下图:
P321
如果采用和单链表相同的内存释放方式,第一步将释放首节点(Head)的内存空间,一直释放到最后一个节点,可是最后一个节点的指针却指向首节点,但首节点早已从内存中释放,如此一来,造成最后一个节点的指针所指的位置是一个内存中早已不存在的数据。
所以我们必须改变一下做法,从思考的全过程中,我们可以采用下列两种方式:
第1种方式:
将循环链表改为单链表,即可用单链表释放的方式。
第一步将Pointer节点指向首节点的指针所指的节点(即第2个节点)。
第二步将首节点的指针指向NULL。
如此一来便成了一个单向的链表。
一个以Pointer节点为首节点的单链表。
Pointer=Head->Next;
Head->Next=NULL;
Head=Pointer;
Delete_List(Head);
图
第2种方式:
从循环链表的第2个节点开始释放
第一步将Pointer节点指向首节点的指针所指的节点(即第2个节点)。
第二步持续往下一个节点释放,直到节点是首节点为止,最后再将首节点释放。
Next=Head->Next;
while(Next!
=Head)
{
Pointer=Next;
Next=Next->Next;
deletePointer;
}
deleteHead;
程序实例:
设计一个将输入的数据建立成循环链表、输出循环链表数据,并释放循环链表。
程序构思:
循环链表的建立:
先声明一个首节点Head,并将Head->Next设为NULL;
每输一笔数据就声明一个新节点New,把New->Next设为NULL,并且链接到之前列表的尾端。
最后一个节点的指针则指向首节点Head。
循环链表的输了出先将Pointer节点的指针指向第一个节点,将Pointer节点(即第一个节点)的数据输了出。
重复执行止步骤直到Pointer节点等等于首节点Head为止。
链接串状链表的释放:
将Pointer节点指向首节点的指针所指的节点(即第二个节点)。
持续往下一个节点释放,直到节点是首节点为止。
最后再将首节点释放。
程序源代码:
#include
#defineMax110
structnode
{
intNumber;
node*Next;
};
//释放循环链表
voiddel_CList(node*Head)
{
node*Pointer;
node*Next;
Next=Head->Next;
while(Next!
=Head)//当下一个节点为首节点时,结束循环
{
Pointer=Next;
Next=Next->Next;
deletePointer;
}
deleteHead;
}
//输出循环链表的数据
voidPrint_CList(node*Head)
{
Node*Pointer;
Pointer=Head;
printf(”请输入数据:
\n”);
do
{
printf(“[%d]”,Pointer->Number);
Pointer=Pointer->Next;
}while(Pointer!
=Head);
printf(“\n”);
}
//建立循环链表
node*Create_CList(node*Head,int*Data,intMax)
{
node*New;
node*Pointer;
inti;
Head=newnode;
if(Head==NULL)
{
printf(“内存申请失败!
\n”);
}
else
{
Head->Number=Data[0];//定义首节点的数据编号
Head->Next=NULL;
Pointer=Head;
for(i=1;i{
New=newnode;
New->Number=Data[i];
New->Next=NULL;
Pointer->Next=New;
Pointer=New;
}
Pointer->Next=Head;
}
returnHead;
}
//主程序
voidmain()
{
node*Head;
Head=Create_CList(Head,Data1,Max1);
if(Head!
=NULL)
{
Print_CList(Head);
}
del_CList(Head);
}
二、循环链表内节点的插入
循环链表内的节点插入,我们可以分为几个情况来讨论:
1、插入在循环链表开头之前
P324
如果新的节点插入在循环链表的开始。
第一步需要将新节点的指针指向循环链表的首节点,第二步将循环链表的最后一个节点的指针指向新的节点,最后再将首节点设为新节点。
New->Next=Head;
Last->Next=New;
Head=New;
图
2、插入在循环链表中间
图
如果新节点插入在循环链表的中间,我们可找到Pointer节点,则需要将新节点的指针指向Pointer节点的指针(即下一个节点),但不能让链表断裂缝。
所以第一步,必须将新节点的指针指向Pointer节点的指针、第二步再将Pointer节点的指针指向新节点。
New->Next=Pointer->Next;
Pointer->Next=New;
图
3、插入在循环链表尾端
图
新的节点插入在循环链表的尾端(Pointer节点),所以第一步,必须将新节点的指针指向Pointer节点的指针(即首节点Head),第二步再将Pointer节点的指针指向新节点。
New->Next=Pointer->Next;
Pointer->Next=New;
图
程序实例:
设计一个循环链表内节点插入的程序。
程序构思:
声明一个新节点供用户输入欲插入节点的内容。
持续往下一个节点,直到节点内容等于Key或节点指针为Head(即找不到该节点)。
如果找到该节点,且该节点的指针是首节点,则插入在环状列表尾端之后:
New->Next=Pointer->Next;
Pointer->Next=New;
如果找到该节点,且该节点的指针不是首节点(Head),则插入在环状列表中间:
New->Next=Pointer->Next;
Pointer->Next=New;
如果找不到,则插入在首节点之前,即首节点之前:
New->Next=Head;
Last->Next=New;
Head=New;
程序源代码:
#include
#defineMax110
structnode
{
intNumber;
node*Next;
};
intData1[Max1]={1,2,3,4,5,6,7,8,9,0};
//释放循环链表
voiddel_CList(node*Head)
{
node*Pointer;
node*Next;
Next=Head->Next;
while(Next!
=Head)
{
Pointer=Next;
Next=Next->Next;
deletePointer;
}
deleteHead;
}
//插入节点至链表内
node*Insert_CList(node*Head,node*New,intKey)
{
node*Pointer;
node*Last;
Pointer=Head;
while
(1)
{
//插入在链表中间或尾端
if(Pointer->Number==Key)
{
New->Next=Pointer->Next;
Pointer->Next=New;
break;
}
//找不到数据,插入在链表首节点前
if(Pointer->Number!
=Key&&Pointer->Next==Head)
{
New->Next=Pointer->Next;
Pointer->Next=New;
Head=New;
break;
}
Pointer=Pointer->Next;
}
returnHead;
}
//输出循环链表数据
voidPrint_CList(node*Head)
{
node*Pointer;
Pointer=Head;
printf(“输出数据:
\n”);
do
{
printf(“[%d]”,Pointer->Number);
Pointer=Pointer->Next;
}while(Pointr!
=Head);
printf(“\n”);
}
//建立循环链表
node*Create_CList(node*Head,int*Data,intMax)
{
node*New;
node*Pointer;
inti;
Head=newnode;
if(Head==NULL)
printf(“内存配置失败!
\n”);
else
{
Head->Number=Data[0];
Head->Next=NULL;
Pointer=Head;
for(i=1;i{
New=newnode;
New->Number=Data[i];
New->Next=NULL;
Pointer->Next=New;
Pointer=New;
}
Pointer->Next=Head;
}
returnHead;
}
//主程序
voidmain()
{
node*Head;
node*New;
intKey;
Head=Create_CList(Head,Data1,Max1);//调用建立环状链接串行
if(Head!
=NULL)
{
Print_CList(Head);
while
(1)
{
printf(“输0退出循环:
”);
New=newnode;
printf(“请输入要插入的数据:
”);
scanf(“[%d]”,&New->Numbe);
if(New->Number==0)
break;
printf(“PleaseinputthedatanumberforInsert:
”);
scanf(“%d”,&Key);
Head=Insert_CList(Head,New,Key);
Print_CList(Head);
}
}
del_CList(Head);
}
三、循环链表内节点的删除
循环链表内节点的删除,依欲删除节点的位置来分,可分为下列几类:
1、删除循环链表首节点
P329
如果欲删除的节点是循环链表的首节点。
第一步需要将首节点指向下一个节点,第二步将循环链表的最后一个节点的指针指向首节点,最后再将原来的节点从内存中释放。
Head=Pointer->Next;
Last->Next=Head;
deletePointer;
图
2、删除循环链表中间节点
图
欲删除的节点在循环链表的中间,如果我们找到Pointer节点,则需要将前一个节点的指针指向Pointer节点的指针(即下一个节点),并将原来的节点从内存中释放。
图
3、删除循环链表尾端的节点
图:
P330
删除的节点在链表的尾端(Pointer节点),如果我们找到Pointer节点,则需要将前一个节点的指针指向Pointer节点(即为首节点)。
并将原来的节点从内存中释放。
Back->Next=Pointer->Next;
deletePointer;
图
程序实例:
设计一个删除循环链表内节点的程序。
程序构思:
持续往下一个节点查找欲删除节点,直到节点内容找到或节点指针为Head(即找不到该节点)。
在删除时,必须记录前一个节点的位置。
如果该节点不存在,输出消息说节点不存在。
如果该节点存在,且是首节点,则必须找到尾端的节点。
Head=Pointer->Next;
Last->Next=Head;
deletePointer;
如果该节点存在,但非首节点(即链表列表中节点或尾端节点),则:
Back->Next=Pointer->Next;
deletePointer;
程序源代码:
#include
#defineMax110
structnode
{
intNumber;
node*Next;
};
IntData1[Max1]={1,2,3,4,5,6,7,8,9,10};
//释放循环链表
voiddel_CList(node*Head)
{
node*Pointer;
node*Next;
Next=Head->Next;
while(Next!
=Head)
{
Pointer=Next;
Next=Next->Next;
deletePointer;
}
}
//删除循环链表内节点
node*del_CList(node*Head,intKey)
{
node*Pointer;
node*Back;
node*Last;
Pointer=Head;
while
(1)
{
if((Pointer->Number!
=Key)&&(Pointer->Next==Head))
{
printf(“NotFound!
!
\n”);
break;
}
if(Head->Number==Key)//删除首节点
{
Last=Head;
while(Last->Next!
=Head)
Last=Last->Next;
Head=Pointer->Next;
Last->Next=Head;
deletePointer;
break;
}
}
returnHead;
}
//输出循环链表数据
voidPrint_CList(node*Head)
{
node*Pointer;
Pointer=Head;
printf(“输出数据:
\n”);
do
{
printf(“[%d]”,Pointer->Number);
Pointer=Pointer->Next;
}while(Pointr!
=Head);
printf(“\n”);
}
//建立循环链表
node*Create_CList(node*Head,int*Data,intMax)
{
node*New;
node*Pointer;
inti;
Head=newnode;
if(Head==NULL)
printf(“内存配置失败!
\n”);
else
{
Head->Number=Data[0];
Head->Next=NULL;
Pointer=Head;
for(i=1;i{
New=newnode;
New->Number=Data[i];
New->Next=NULL;
Pointer->Next=New;
Pointer=New;
}
Pointer->Next=Head;
}
returnHead;
}
//主程序
voidmain()
{
node*Head;
intKey;
Head=Create_CList(Head,Data1,Max1);//调用建立环状链接串行
if(Head!
=NULL)
{
Print_CList(Head);
while
(1)
{
printf(“输0退出循环:
”);
New=newnode;
printf(“请输入要删除的数据:
”);
scanf(“[%d]”,&Key);
if(Key==0)
break;
Head=del_CList(Head,Key);
Print_CList(Head);
}
}
del_CList(Head);
}