循环链表与约瑟夫环

循环链表的实现

尾插法

头插法

删除元素

查找元素

#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

class CircleLink
{
public:
    CircleLink(){
        head = new ListNode();
        tail = head;
        head -> next = head;
    }
    ~CircleLink(){
        ListNode *p = head->next;
        while(p!=head){
            head->next = p -> next;
            delete p;
            p = head->next;
        }
        delete head;
    }
public:
    void InsertTail(int val){
        ListNode * node = new ListNode(val);
        node->next = tail->next; //先要让新节点的下一个指向当前node节点的下一个节点
        tail->next = node;  //更换当前tail指向的节点,把node插进来
        tail = node; //此时node节点变成了尾部节点,tail一直指向尾节点,在此将tail指向node完成tail节点的移动
    }
    void InsertHead(int val){
        ListNode * node = new ListNode(val);
        node->next = head -> next;
        head->next = node;
        if(node->next == head){//如果是链表初始是空的,那么需要把tail指向当前插入的节点node
            tail = node;
        }
    }
    bool DeleteNode(int val) { 
        ListNode *q = head;
        ListNode *p = head->next;
        while(p!=head){
            if(p->data!=val){
                q=p;
                p = p->next;
            }else{
                q->next = p->next;
                delete p;
                //判断,当q的下一个节点是头节点时,代表当前节点q是末尾节点,要把tail节点更新
                if(q->next == head){
                    tail = q;
                }
                return true;
            }
        }
        return false;
    }
    bool Find(int val) const { 
        ListNode *p=head->next;
        while(p!=head){ 
            if(p->data==val){
                return true;
            }else{
                p=p->next;
            }
        }
        return false;
    }
    void show() const {
        ListNode *p = head->next;
        while(p!=head){
            cout<<p->data<<"   ";
            p=p->next;
        }
        cout<<endl;
    }
private:
    struct ListNode{
        ListNode(int data=0):data(data),next(nullptr){};
        int data;
        ListNode *next;
    };
    ListNode *head;
    ListNode *tail;
};

int main(){
    CircleLink link1;
    CircleLink link2;
    srand(time(NULL));
    for(int i=0;i<10;i++){
        int a =rand()%1000;
        link1.InsertHead(a);
        link2.InsertTail(a);
    }
    link1.show();
    link2.show();
    link1.InsertHead(9999);
    link2.InsertTail(9999);
    link1.show();
    link2.show();
    link1.Find(9999);
    link2.Find(9999);
    link1.DeleteNode(9999);
    link2.DeleteNode(9999);
    link1.show();
    link2.show();
}

不带头节点的约瑟夫问题解法

约瑟夫环问题:已知n个人,(以编号1,2,3,。。。n分别表示)围坐在一张圆桌周围,从编号为k的人开始报数,数到m的那个人出列,它的下一个人又从1开始报数,数到m的那个人又出列,依次规律重复下去,知道圆桌周围的人全部出列,输出人的出列顺序

#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;

//单链表的实现
struct ListNode{
        ListNode(int data=0):data(data),next(nullptr){};
        int data;
        ListNode *next;
    };
void Joseph(ListNode *node,int k ,int m){
   // ListNode head = new ListNode();
   // head->next = node;
    ListNode *p = node;
    ListNode *q = node;
    while(q->next!=node){
        q=q->next;
    }
    //找起始节点
    for(int i=1;i<k;i++){
        q=p;
        p=p->next;
    }
    while(1){
        for(int i=1;i<m;i++){
            q=p;
            p=p->next;
        }
        cout<<p->data<<"    ";
        if(p==q){
            delete p;
            break;
        }
        q->next = p->next;
        delete p;
        p = q->next;
    }
}
int main(){
    ListNode *node = new ListNode(1);
    ListNode *n1 = new ListNode(2);
    ListNode *n2 = new ListNode(3);
    ListNode *n3 = new ListNode(4);
    ListNode *n4 = new ListNode(5);
    ListNode *n5 = new ListNode(6);
    ListNode *n6 = new ListNode(7);
    ListNode *n7 = new ListNode(8);
    ListNode *n8 = new ListNode(9);
    node->next = n1;
    n1->next=n2;
    n2->next=n3;
    n3->next=n4;
    n4->next=n5;
    n5->next=n6;
    n6->next=n7;
    n7->next=n8;
    n8->next=node;
    Joseph(node,1,5);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值