1、单向循环链表一
1)特点
每一个节点除了数据域,还有一个next指针域指向下一个节点(存储了下一个节点的地址)
末尾节点的指针域指向了头节点
析构函数思路图
2)代码实现
//定义结点
//单向循环链表
class CircleLink
{
public:
//构造函数
CircleLink()//这里是生成一个带头节点的
{
head_ = new Node();
tail_ = head_;
head_->next_ = head_;
}
//析构函数
~CircleLink()//析构函数
{
Node* p = head_->next_;
while(p != head_)
{
head_->next_ = p->next_;
delete p;
p = head_->next_;
}
delete head_;
}
//共有方法区域
public:
//尾插法 O(1)
void InsertTail(int val)
{
Node* node = new Node(val);
node->next_ = head_; //node->next_ = tail_->next_;
tail_->next_ = node;
tail_ = node; //更新tail_ 指针 指向新的尾节点
}
//头插法
void InsertHead(int val)
{
Node* node = new Node(val);
node->next_ = head_->next_;
head_->next_ = node;
//万一是空链表,要处理tail_
if(node->next_ == head_)
tail_ = node;
}
//删除节点
void Remove(int val)
{
Node* q = head_;
Node* p = head_->next_;
while( p != head_ )
{
if( p->data_ == val )
{
//找到删除节点
//if(p == tail_)
// tail_ = q;
q->next_ = p->next_;
delete p;
//防止所删除的数据为尾节点,重置尾节点
if(q->next_ == head_)
{
tail_ = q;
}
return ;
}
else
{
p = p->next_;
q = q->next_;
}
}
}
//查询
bool Find(int val) const
{
Node* p = head_->next_;
while(p != head_)
{
if(p->data_ == val)
{
return true;
}
else
{
p = p->next_;
}
}
return false;
}
//打印链表
void Show() const
{
Node* p =head_->next_;
while (p != head_)
{
cout<<p->data_<< " " ;
p = p->next_;
}
cout<< endl;
}
private:
struct Node
{
Node(int date = 0):data_(date),next_(nullptr){}
int data_;
Node* next_;
};
Node* head_; // 指向头节点
Node* tail_; //指向末尾节点
};
代码测试
int main()
{
CircleLink clink;
srand((time(NULL)));
//尾插
for(int i = 0; i <10;i++)
{
clink.InsertTail(rand() % 100);
}
clink.Show();
//头插
for(int i = 0; i <5;i++)
{
clink.InsertHead(i);
}
clink.Show();
//删除
clink.InsertTail(0);
clink.Show();
clink.Remove(0);
clink.Show();
clink.Remove(0);
clink.Show();
}
测试结果:
2、约瑟夫环问题
约瑟夫环是一个数学的应用问题: 已知n个人 (以编号1,2,3…n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,它的下一个人又从1开始报数,数到m的那个人又出列,依此规律重复下去,直到圆桌周围的人全部出列,输出人的出列顺序。
代码实现1 – 不带头节点
#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <string.h>
using namespace std;
struct Node
{
Node(int date = 0):data_(date),next_(nullptr){}
int data_;
Node* next_;
};
//约瑟夫环问题
void Joseph(Node* head,int k,int m)//这里指针指向的是第一个节点,该算法为不带头节点的单向循环链表应用
{
Node* p = head;
Node* q = head;
//q指向最后一个节点,防止m==1 的特殊情况
while(q->next_ != head)
{
q = q->next_;
}
//从第k个人开始报数的
for(int i = 1; i < k; i++)
{
q = p;
p = p->next_;
}
//走到地m个人
for(;;)
{
for(int i = 1; i<m; i++)
{
q = p;
p=p->next_;
}
//打印符合条件的节点数据
cout<<p->data_ << " ";
//删除p指向的节点
if(p == q)//剩余最后一个节点
{
delete p;
break;
}
/*if(p == head)//所删除节点为头节点
{
head = q->next_;
}*/
q->next_ = p->next_;
delete p;
p=q->next_;
}
cout<<endl;
}
测试代码
int main()
{
Node *head = new Node(1);
Node *n2 = new Node(2);
Node *n3 = new Node(3);
Node *n4 = new Node(4);
Node *n5 = new Node(5);
Node *n6 = new Node(6);
Node *n7 = new Node(7);
Node *n8 = new Node(8);
head->next_ = n2;
n2->next_ = n3;
n3->next_ = n4;
n4->next_ = n5;
n5->next_ = n6;
n6->next_ = n7;
n7->next_ = n8;
n8->next_ = head;
Joseph(head,1,3);
//Joseph(head,1,1);
return 0;
}
运行结果
Joseph(head,1,3);
Joseph(head,1,1);