一.实验目的(Objects)
1.掌握循环单链表的生成及插入删除的实现方法和应用。
二.实验内容(Contents)
1.约瑟夫环(改造版)描述
编号为 1,2,…,n的 n个人按顺时针方向围坐在一圈,每人持有一个密码(正整数)。一开始任选一 个正整数作为报数值 m,从第一个人开始按顺时针方向自 1开始顺序报数,报到 m时停止报数。报 m 的人出列,将他的密码作为新的 m值,从他在顺时针方向上的下一个人开始重新从 1报数,如此下去, 直至所有人都出列为止。请设计一个程序求出出列顺序。
2.基本要求(BasicRequirements)
利用单项循环链表存储结构模拟次过程,按照出列的顺序打印出个人的编号。
3.测试数据(testdata)
m的初值为 20;n=7,7个人的密码一次为:3,1,7,2,4,8,4,首次 m值为 20(正确的出列顺序应为 6,1,4,7,2,3,5)。
4.实现提示(implementationtips)
程序运行后,首先要求用户指定初始报数值,然后读取个人的密码。
三.实验步骤(Yourstepsorcodes)
1st.整体设计(Overalldesign)
基本设计思想是,使用两个简单链表 tt,t,t存储编号和对应的密码,tt存储出位顺序,对 t进行约瑟夫规 则处理,逐次找到出位顺序的编号依次存入 tt链表中,在 t链表中的节点处理完成后,对 tt链表进行遍历, 即可得到出位顺序。
整体的类变量声明和基本函数声明如下:
template<typenameT>
structnode{
public:
T number;
T password;
node<T>*next;
};
template<typenameT>
classlink{
node<T>*header;
public:
link();
~link();
node<T>*back()const;
int len_link()const;
void trave_two()const;
void trave_one()const;
void create_new_node(const int a,const int b);
void create_new_node(const int a);
void replace_password(const int a,int password);
void delete_link();
void remove_one_node(node<T>*p);
int remove_more(const int x);
node<T>*find_id(const int x);
node<T>*loaction(int x);
voidinsert(node<T>*p,node<T>*q);
intback_name(const int t);
};
template<typenameT>
classJoseph_ring{
private:
link<T>t;
link<T>tt;
node<T>*q;
node<T>*p;
int m;
public:
Joseph_ring(int a);
~Joseph_ring();
void pro_system();
void Generate_list(T*a,T n);
void trave_tw(){
t.trave_two();
}
void trave_on(){
tt.trave_one()
}
};
关于 link类和 Joseph_ring的核心函数,我会在算法框架里具体分析,这里不做赘述。
2nd.算法框架(Algorithm Framework)
1.关于 link类核心函数的算法框架
主要核心函数如下:
void create_new_node(const int a,const int b);
void insert(node<T>*p,node<T>*q);
void remove_one_node(node<T>*p);
int len_link()const;
void trave_two()const;
1>.关于创建节点的函数
函数的具体定义如下:
template<typenameT>
voidlink<T>::create_new_node(constinta,constintb){
if(header==nullptr){
header=new node<T>;
header->number=a;
header->password=b;
header->next=nullptr;
}
else{
node<T>*q;
q=header;
while(q->next!=nullptr){
q=q->next;
}
node<T>*p;
p=new node<T>;
p->number=a;
p->password=b;
q->next=p;
p->next=nullptr;
}
}
正如上面注释部分写的那样,考虑两种情况,链表为空和链表不为空。链表为空直接加入头节点,不为空,借助两个辅助指针 p,q完成。这个基本算法很简单。
2>.关于插入节点的函数
template<typename T>
void link<T>::insert(node1<T>*p, node1<T>*q) {
node1<T>*tt = new node1<T>;
tt = header;
if (p->next == nullptr) {
p->next = q;
q->next = nullptr;
}
else {
while (tt != p) {
tt = tt->next;
if (tt == nullptr)
break;
}
if (tt) {
q->next = tt->next;
tt->next = q;
}
else
cout << "不存在p节点!\n";
}
}
在 p节点后插入 q节点,首先应该先连接 q节点与 p后面的节点,然后再连接 p与 q节点。这是需要注 意的地方,不然很可能会让原 p节点后面的节点丢失找不到。
3>.关于删除节点的函数
template<typename T>
void link<T>::remove_one_node(node1<T>*p) {
node1<T>*prve;
prve = header;
if (p == prve)
header = p->next;
else
{
while (prve->next != p) {
prve = prve->next;
}
prve->next = p->next;
}
delete p;
}
在找到想要删除的节点 p时,为了不让在删除 p节点后链表断裂,应该先让 p前节点与 p后节点接在一 起。
4>.计算链表的长度
template<typename T>
int link<T>::len_link()const {
node1<T>*p;
p = header;
int k = 0;
while (p != nullptr) {
k++;
p = p->next;
}
return k;
}
使用 k值计算链表的节点个数,对链表进行遍历,每次碰到不为空的节点则 k++,直到节点为空为止。
5>.链表的遍历函数
template<typename T>
void link<T>::trave_two()const {
node1<T> *cour;
cour = header;
if (cour == nullptr)
;
else {
while (cour != nullptr) {
cout << "Number: \t" << cour->number << "\t";
cout << "Password: \t" << cour->password << "\n";
cour = cour->next;
}
cout << endl;
}
}
2.关于 Joseph_ring类核心函数的算法框架
主要核心函数如下:
void pro_system();
void Generate_list(T*a,T n);
1>.关于 pro_system 函数
template<typename T>
void Joseph_ring<T>::Generate_list(T *a, T n) {
int i, j = 1;
for (i = 0; i < n; j++, i++)
t.create_new_node(j, a[i]);
p = t.back();
}
在这里调用链表的创建函数。
2>.关于 Generate_list函数
template<typename T>
void Joseph_ring<T>::pro_system() {
int i = 2;
while (i <= m) {
if (p->next == nullptr)
p = t.back();
else
p = p->next;
i++;
}
tt.create_new_node(p->number);
if (p->next != nullptr)
q = p->next;
else
q = t.back();
m = p->password;
t.remove_one_node(p);
p = q;
if (t.back() != nullptr) {
pro_system();
}
}
正如上述注释所说,首先对初始 m值进行操作,使用循环,查询到 m时的人的编号放入 tt链表内。然后 加入判断,如果查询到 t链表尾部,返回头部接着进行。并且更新 m值为此时 p->password。然后删除 t 链表中的 p。
四.测试用例(Results)
测试用例为: m的初值为 20;n=7,7个人的密码一次为:3,1,7,2,4,8,4,首次 m值为 20(正确的出列顺序应为 6,1,4,7,2,3,5)。
五.源程序(SourceProgram)
#include "pch.h"
#include<iostream>
using namespace std;
template<typename T>
struct node1 {
public:
T number;
T password;
node1<T> *next;
};
template<typename T>
class link {
node1<T> *header;
public:
link();
~link();
node1<T>* back()const;
int len_link()const;
void trave_two()const;
void trave_one()const;
void create_new_node(const int a, const int b);
void create_new_node(const int a);
void replace_password(const int a, int password);
void delete_link();
void remove_one_node(node1<T>*p);
int remove_more(const int x);
node1<T>*find_id(const int x);
node1<T>*loaction(int x);
void insert(node1<T>*p, node1<T>*q);
int back_name(const int t);
};
template<typename T>
link<T>::link() {
header = nullptr;
}
template<typename T>
link<T>::~link() {
delete_link();
}
template<typename T>
node1<T>* link<T>::back()const {
return header;
}
template<typename T>
int link<T>::len_link()const {
node1<T>*p;
p = header;
int k = 0;
while (p != nullptr) {
k++;
p = p->next;
}
return k;
}
template<typename T>
void link<T>::trave_two()const {
node1<T> *cour;
cour = header;
if (cour == nullptr)
;
else {
while (cour != nullptr) {
cout << "Number: \t" << cour->number << "\t";
cout << "Password: \t" << cour->password << "\n";
cour = cour->next;
}
cout << endl;
}
}
template<typename T>
void link<T>::trave_one()const {
node1<T> *cour;
cour = header;
if (cour == nullptr)
;
else {
while (cour != nullptr) {
cout << cour->number << ' ';
cour = cour->next;
}
cout << endl;
}
}
template<typename T>
void link<T>::create_new_node(const int a, const int b) {
if (header == nullptr) {
header = new node1<T>;
header->number = a;
header->password = b;
header->next = nullptr;
}
else {
node1<T>*q;
q = header;
while (q->next != nullptr) {
q = q->next;
}
node1<T>*p;
p = new node1<T>;
p->number = a;
p->password = b;
q->next = p;
p->next = nullptr;
}
}
template<typename T>
void link<T>::create_new_node(const int a) {
if (header == nullptr) {
header = new node1<T>;
header->number = a;
header->next = nullptr;
}
else {
node1<T>*q;
q = header;
while (q->next != nullptr) {
q = q->next;
}
node1<T>*p;
p = new node1<T>;
p->number = a;
q->next = p;
p->next = nullptr;
}
}
template<typename T>
void link<T>::replace_password(const int a, int password) {
node1<T>*p;
p = header;
while (p != nullptr) {
if (p->number == a) {
p->password = password;
break;
}
p = p->next;
}
}
template<typename T>
void link<T>::remove_one_node(node1<T>*p) {
node1<T>*prve;
prve = header;
if (p == prve)
header = p->next;
else
{
while (prve->next != p) {
prve = prve->next;
}
prve->next = p->next;
}
delete p;
}
template<typename T>
void link<T>::delete_link() {
node1<T>*p;
node1<T>*q = nullptr;
p = header;
while (p != nullptr) {
q = p->next;
remove_one_node(p);
p = q;
}
header = nullptr;
}
template<typename T>
int link<T>::remove_more(const int x) {
int k = 0;
node1<T>* p;
node1<T>* q = nullptr;
p = header;
while (1)
{
if (p->number == x) {
q = p->next;
remove_one_node(p);
p = q;
k++;
}
else
p = p->next;
if (p == nullptr)
break;
}
return k;
}
template<typename T>
node1<T>* link<T>::find_id(const int x) {
node1<T>* p;
node1<T>* q;
q = p = header;
while (1) {
if (p->number == x) {
return q;
break;
}
p = p->next;
q = q->next;
if (q == nullptr) {
return q;
break;
}
}
}
template<typename T>
node1<T>* link<T>::loaction(int x) {
node1<T>*p;
p = header;
int m = 0;
while (p != nullptr)
{
m++;
p = p->next;
}
p = header;
if (x <= m) {
int i;
if (x == 1)
;
else {
for (i = 2; i <= x; i++)
p = p->next;
}
return p;
}
else
return nullptr;
}
template<typename T>
int link<T>::back_name(const int t) {
node1<T>*p;
p = header;
while (p != nullptr) {
if (p->number == t) {
return p->mi;
break;
}
p = p->next;
}
}
template<typename T>
void link<T>::insert(node1<T>*p, node1<T>*q) {
node1<T>*tt = new node1<T>;
tt = header;
if (p->next == nullptr) {
p->next = q;
q->next = nullptr;
}
else {
while (tt != p) {
tt = tt->next;
if (tt == nullptr)
break;
}
if (tt) {
q->next = tt->next;
tt->next = q;
}
else
cout << "不存在p节点!\n";
}
}
template<typename T>
class Joseph_ring {
private:
link<T> t;
link<T> tt;
node1<T>* q;
node1<T>* p;
int m;
public:
Joseph_ring(int a);
~Joseph_ring();
void pro_system();
void Generate_list(T *a, T n);
void trave_tw() {
t.trave_two();
}
void trave_on() {
tt.trave_one();
}
};
template<typename T>
Joseph_ring<T>::Joseph_ring(int a) :m(a) {
q = nullptr;
p = nullptr;
}
template<typename T>
Joseph_ring<T>::~Joseph_ring() {
}
template<typename T>
void Joseph_ring<T>::Generate_list(T *a, T n) {
int i, j = 1;
for (i = 0; i < n; j++, i++)
t.create_new_node(j, a[i]);
p = t.back();
}
template<typename T>
void Joseph_ring<T>::pro_system() {
int i = 2;
while (i <= m) {
if (p->next == nullptr)
p = t.back();
else
p = p->next;
i++;
}
tt.create_new_node(p->number);
if (p->next != nullptr)
q = p->next;
else
q = t.back();
m = p->password;
t.remove_one_node(p);
p = q;
if (t.back() != nullptr) {
pro_system();
}
}
int main()
{
int m;
cout << "Please input your numbers that you want to test: " << endl;
int n;
cin >> n;
if (n > 0) {
int *a;
a = new int[n];
cout << "Please enter everyone's password in turn: \n";
for (int i = 0; i < n; i++) {
cin >> a[i];
}
cout << "Please enter the initial password [m]: \n";
cin >> m;
Joseph_ring<int> Jose(m);
Jose.Generate_list(a, n);
cout << "We will perform the Joseph loop operation for the initial password m: [" << " " << m << " ]\n";
cout << "Everyone's number and password om order as follows: \n";
Jose.trave_tw();
Jose.pro_system();
cout << "The following is the order in which people are out: \n";
Jose.trave_on();
delete[]a;
}
else {
cout << "There was a mistake in the number of people entered!\n";
}
return 0;
}
使用源程序的小伙伴支持一下,给个赞和收藏,最好也评论下。谢谢 作者大大深夜发文也不容易 哈哈哈!!
|