循环链表概念
循环链表是另一种形式的链式存贮结构。它的特点是表中最后一个结点的指针域指向头结点,整个链表形成一个环。
完整代码实现
#include<iostream>
#include<string>
#include<stdlib.h>
using namespace std;
typedef struct _LinkNode {
int data; //结点的数据域
struct _LinkNode *next; //结点的指针域
}LinkNode, LinkList; //LinkList 为指向结构体 LNode 的指针类型
void LinkPrint(LinkList *L);
bool InitList(LinkList* &L)//构造一个空的循环链表 L
{
L=new LinkNode; //生成新结点作为头结点,用头指针 L 指向头结点
if(!L)return false; //生成结点失败
L->next=L; //头结点的指针域指向自己
L->data = -1;
return true;
}
//尾插法
bool ListInsert_back(LinkList* &L, LinkNode * node){
LinkNode *last = NULL;
if(!L || !node ) return false;
//找到最后一个节点
last = L;
while(last->next!=L) last=last->next;
//新的节点链接到最尾部
node->next = L;
last->next = node;
return true;
}
bool TestOut(LinkList* &L, int interval)
{
//在带头结点的循环链表 L 中,每个 interval 个间隔循环删除节点
LinkList *p, *q;
int j = 0, i = 0;
int times = 0, num = 0;
p=L;
if(!L || p->next == L) {
cout<<"链表为空!"<<endl;
return false;
}
if(interval<1){
cout<<"报数淘汰口令不能小于 1!"<<endl;
return false;
}
do{
i += interval;
while((p->next)) //查找第 i 个结点,p 指向该结点的上一个节点
{
if(p->next!=L) j++;
if(j>=i) break;
p=p->next;
}
times++;
q=p->next; //临时保存被删结点的地址以备释放空间
num = q->data;
if(times==5) cout<<"第 5 个出圈的编号是:"<<num<<endl;
printf("cur: %d last: %d next:%d\n",q->data, p->data,q->next->data);
p->next=q->next; //改变删除结点前驱结点的指针域
delete q; //释放被删除结点的空间
LinkPrint(L);
}while(L->next!=L);//链表不为空,继续报数
cout<<"最后一个出圈的编号是:"<<num<<endl;
return true;
}
void LinkPrint(LinkList *L) //循环链表的输出
{
LinkList *p;
if(!L || L==L->next){
cout<<"链表为空!"<<endl;
return ;
}
p=L->next;
while (p!=L)
{
cout <<p->data <<"\t";
p=p->next;
}
cout<<endl;
}
int main(){
int i, x;
LinkList *L;
LinkNode *s;
//1. 初始化一个空的循环链表
if (InitList(L)){
cout << "初始化一个空的循环链表!\n";
}
//2. 创建循环链表(尾插法)
std::cout <<"尾插法创建循环链表, 插入 10 个元素..." <<endl;
i = 0;
while((++i)<=10)
{
s=new LinkNode;//生成新结点
s->data=i; //输入元素值赋给新结点的数据域
s->next=NULL;
if(ListInsert_back(L, s)){
cout<<"插入成功!"<<endl;
}else {
cout<<"插入失败!"<<endl;
}
}
cout << "尾插法创建循环链表输出结果:\n";
LinkPrint(L);
TestOut(L, 9);
system("pause");
return 0;
}