约瑟夫算法(基于C++链表实现)-我的链表使用心得

来源:互联网 发布:淘宝搜索 编辑:程序博客网 时间:2024/06/14 18:42

首先,我想说下,本人发表这篇文章,只是用于自己整理C++中链表使用的思路,所用内容都是本人对链表的理解,所以请慎重评价!同时希望那些和我一样开始接触链表的人能对链表有更好的理解!

写这篇文章是因为最近自己在做数据结构的作业,要求实现约瑟夫算法:

约瑟夫(Joseph)问题的一种描述是:编号为12, 。。。,nn个人按顺时针方向围坐一圈,每人持有一个密码(正整数)。一开始任选一个正整数作为报数上限值m,从第一个人开始按顺时针方向自1开始顺序报数,报到m时停止报数。报到m的人出列,将他的密码作为新的m值,从他在顺时针方向上的下一个人开始重新从1报数,如此下去,直到所有人全部出列为止。试设计一个程序求出出列顺序。

这里,选择使用链表来实现,具体的使用单链表中的循环链表来实现。

首先先说下链表的实现,

1>为了创建一个链表,首先先建一个节点结构:

struct Node{

   int Data;

   Node *next;

};

节点的数据域存放计算的数据,节点的next指针域存放指向下一节点的地址

2>然后创建我们的链表类List类,

在List类中我们要添加实现链表操作的方法,包括:

List();

void insertNode(int val);//插入到所给值得前面

void deleteNode(int val);

bool empty();

void outputNode();

还要添加一个私有成员, Node *head; 即头指针;

构造函数:  初始化head = NULL;

插入操作:首先新建节点并初始化,Node *s;

                                                s = (Node*)new(Node);

                                                s->Data = val;

               进行一下判断:(1).if(head==NULL)//头指针为空

                                    (2).Node *p = head;

                                         if(p->Data==val)//插入点为第一个节点

                                    (3).Node *q;

                                         while(p->Data != val)//循环寻找插入节点

                                    (4).if(p->next == NULL)//插入节点是尾节点

删除操作:首先建两个指针,Node *p,*q;

               判断:(1).if(head == NULL)//链表为空

                        (2).p= head;

                             if(p->Data == val)//删除节点是第一个节点

                        (3).while((p->Data != val)&&(p->next != NULL))//循环寻找删除节点

                        (4).if(p->Data == val)找到节点

                             if(p->next == NULL)//节点不存在

判空操作:这是一个可选的方法,return head == NULL;//判断链表是否为空

输出操作:定义一个指针,Node *current;

                      初始化为  current = head;

                      循环输出  while(current->next != NULL)

以上就是一个能实现基本操作的链表类,这里只给出了算法,希望大家能够理解

3>下面说下约瑟夫算法的实现,使用循环链表

循环链表同单链表基本相似,只是循环链表尾节点的next指针始终指向链表的首地址,因此在插入删除操作时会有些不同的地方

节点结构同上,

为了实现约瑟夫算法,添加如下方法:

List();

void init(int val);//向链表中添加值

void deleteNode(int val);

bool empty();

void output();

void calculate();//计算约瑟夫算法

void setM(int val);

添加私用成员,Node *head;

                     int m;

                     int counter;//记录链表中的节点的个数

构造函数: head= (Node*)new(Node);

              counter = 0;

              head->Data = counter;

              head->next = NULL;

插入操作://这里为了具体实现约瑟夫算法,只是在链表的结尾添加数值

              Node *s,*p;

              s = (Node*)new(Node);

              s->Data = val;

              if(head->next == NULL)//首节点

                 head->next = s;

                 s->next = head->next;

                 counter++;

                 head->Data = counter;

              else 

                 p = head->next;

                 while(p->next != head->next)//找到链表尾节点

                 p = p->next;

                 p->next = s;

                 s->next = head->next;

                 counter++;

                 head->Data = counter;

删除操作: //这里和单链表不太一样

               Node *p,*q;

              p=head->next;

              if(head->next == NULL)//空链表

                   return;

              if(p->next == head->next)//p是第一个节点,这时候要把尾节点的next指针指向第二个节点

                    q = p;

                  while(q->next != head->next)//找到尾节点

                             q = q->next;

                    head->next = p->next;

                    q->next = head->next;将新的头结点next域赋给尾节点的next域

                    delete p;

                    counter--;

                    head->Data = counter;

              while(p->Data != val)//寻找节点

                    q = p;

                    p = p->next;

              q->next = p->next; 

              delete p; 

              counter--; 

              head->Data = counter;

输出操作:Node *current = head->next;

              while(current->next != head->next)//输出节点

判空操作: return head->Data == 0;

计算操作: Node *temp;//用来存放循环的下一节点的指针

                temp = head->next;

       loop:    Node *p;//这里使用的是goto语句,当然也可以用其他的方法:)

                  p = temp;

                 int count = 1;//计数器

                 while(count != m)

                           count++;

                           p= p->next;

                 m = p->Data;

                 temp = p->next;//保护现场:赋值,存放指针

                 deleteNode(p->Data);

                 if(!empty())//判空

                       output();

                       goto loop;

                 else

                       cout<<"FINISH!"<<endl;

setM(int val): m = val ;

这里想说的是,在删除循环链表的第一个节点的时候,不要忘了给尾节点的next指针赋一个新的值!

 

以上就是链表类中所有的内容,另外我在文章结尾附有完整的程序,有什么问题,还请大家指证!

 

这是我第一次写文章,所以有什么不足之处还请大家海涵!

 

约瑟夫算法基于C++链表实现--完整

 

#include<iostream>

using namespace std;

struct Node

{

int Data;

Node * next;

};

class List

{

private:

Node * head;

int m;

int counter;

public:

List()

{

head = (Node*)new(Node);

head->next = NULL;

counter = 0;

}

bool empty()

{

return head->Data == 0;

}

void init(int v)

{

Node *s,*p;

s = (Node*)new(Node);

s->Data = v;

if(head->next == NULL)

{

head->next = s;

s->next = head->next;

counter++;

head->Data = counter;

}

else

{

p = head->next;

while(p->next != head->next)

{

p = p->next;

}

p->next = s;

s->next = head->next;

counter++;

head->Data = counter;

}

}

    void deleteNode(int v)

{

Node *p,*q;

if(head->next == NULL)

{

return;

}

else

{

p = head->next;

if(p->Data == v)

{

q = p;

while(q->next != head->next)

{

q = q->next;

}

head->next = p->next;

q->next = head->next;

delete p;

counter--;

head->Data = counter;

}

else

{

while(p->Data != v)

{

q = p;

p = p->next;

}

q->next = p->next;

delete p;

counter--;

head->Data = counter;

}

}

}

void outputNode()

{

Node *current;

current = head->next;

int i = 0;

while(current->next != head->next)

{

cout<<"NO."<<(i+1)<<"  "<<current->Data<<"   ";

current = current->next;

i++;

}

cout<<"NO."<<(i+1)<<"  "<<current->Data<<"   ";

cout<<endl;

}

    void calcute()

{

Node *temp;

temp = head->next;

int data[1024];

int number = 0;

 loop : Node *p;

p = temp;

int count = 1;

while(count != m)

{

count++;

p = p->next;

}

temp = p->next;

m = p->Data;

data[number] = p->Data;

number++;

deleteNode(p->Data);

if(!empty())

{

outputNode();

//getchar();

goto loop;

}

else

{

cout<<"FINISH ! The output order is as follow :"<<endl;

for(int i = 0;i<number;i++)

{

cout<<"ORDER."<<(i+1)<<": "<<data[i]<<"  ";

}

 

}

}

void setM(int v)

{

m = v;

}

int getCounter()

{

return counter;

}

};

 

 

原创粉丝点击