数据结构之循环链表建议收藏

一循环链表基础在单链表中,有了头结点,我们可以在O(1)时间访问到第一个节点,但如果要访问最后一个节点却需要O(n)的时间,因为我们需要对整个链表进行一次遍历。在循环链表中,我们可以借助尾节点来实

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

全栈程序员社区此处内容已经被作者隐藏,请输入验证码查看内容
验证码:
请关注本站微信公众号,回复“验证码”,获取验证码。在微信里搜索“全栈程序员社区”或者“www_javaforall_cn”或者微信扫描右侧二维码都可以关注本站微信公众号。

一 循环链表基础

  在单链表中,有了头结点,我们可以在O(1)时间访问到第一个节点,但如果要访问最后一个节点却需要O(n)的时间,因为我们需要对整个链表进行一次遍历。在循环链表中,我们可以借助尾节点来实现,即不用头指针,而是用指向终端结点的尾指针来表示循环链表,这时候无论是查找第一个节点还是最后一个节点都很方便,可以控制在O(1)的时间内,如下图所示。

 数据结构之循环链表建议收藏

二 代码实现

(1)循环链表初始化

template <typename T>
struct Node
{
    T data;
    Node<T>* pNext;
};

void InitList()
{
    // 删除所有节点
    Clear();
    m_pHead = new Node<T>;
    memset(m_pHead,0, sizeof(Node<T>));
    m_pHead->pNext = m_pHead;
}        

(2)循环链表新结点插入

// 从尾部添加节点
void AddNode(T data)
{
    Node<T> *pNode = new Node<T>;
    pNode->data = data;

    Node<T>* pTemp = m_pHead;
    while (pTemp->pNext!= m_pHead)
    {
        pTemp = pTemp->pNext;
    }
    pNode->pNext = pTemp->pNext;
    pTemp->pNext = pNode;
}

(3)循环链接结点删除

void DeleteNode(T data)
{
    Node<T> *pNode = m_pHead;
    Node<T> *pTemp = NULL;

    while (pNode->pNext != m_pHead)
    {
        if (pNode->pNext->data == data)
        {
            pTemp = pNode->pNext;
            pNode->pNext = pTemp->pNext;
            delete pTemp;
        }
        else
        {
            pNode = pNode->pNext;
        }
    }
}

(4)删除循环链表

void Clear()
{
    if (NULL == m_pHead)
    {
        return;
    }

    Node<T>* pTemp = NULL;
    Node<T>* pNode = m_pHead->pNext;
    while (pNode != m_pHead)
    {
        pTemp = pNode;
        pNode = pNode->pNext;
        delete pTemp;
    }

    delete pNode;

(5)打印循环链表

void PrintList()
{
    Node<T>* pNode = m_pHead->pNext;
    while (pNode != m_pHead)
    {
        cout << pNode->data << " ";
        pNode = pNode->pNext;
    }

    cout << endl;
}

(6)代码

数据结构之循环链表建议收藏
数据结构之循环链表建议收藏

#include "stdio.h"
#include <iostream>
using namespace std;

template <typename T>
struct Node
{
    T data;
    Node<T>* pNext;
};

// 主要实现循环链表的添加、删除和打印
template <typename T>
class CircList
{
public:
    CircList()
    {
        m_pHead = NULL;
        nLen = 0;
    }
    ~CircList()
    {
        Clear();
        m_pHead = NULL;
    }
    
    void InitList()
    {
        // 删除所有节点
        Clear();
        m_pHead = new Node<T>;
        memset(m_pHead,0, sizeof(Node<T>));
        m_pHead->pNext = m_pHead;
    }
    // 从尾部添加节点
    void AddNode(T data)
    {
        Node<T> *pNode = new Node<T>;
        pNode->data = data;

        Node<T>* pTemp = m_pHead;
        while (pTemp->pNext!= m_pHead)
        {
            pTemp = pTemp->pNext;
        }
        pNode->pNext = pTemp->pNext;
        pTemp->pNext = pNode;

        nLen ++; 
    }
    void DeleteNode(T data)
    {
        Node<T> *pNode = m_pHead;
        Node<T> *pTemp = NULL;

        while (pNode->pNext != m_pHead)
        {
            if (pNode->pNext->data == data)
            {
                pTemp = pNode->pNext;
                pNode->pNext = pTemp->pNext;
                delete pTemp;
            }
            else
            {
                pNode = pNode->pNext;
            }
        }

        nLen --;
    }

    void PrintList()
    {
        Node<T>* pNode = m_pHead->pNext;
        while (pNode != m_pHead)
        {
            cout << pNode->data << " ";
            pNode = pNode->pNext;
        }
    }

    void Clear()
    {
        if (NULL == m_pHead)
        {
            return;
        }

        Node<T>* pTemp = NULL;
        Node<T>* pNode = m_pHead->pNext;
        while (pNode != m_pHead)
        {
            pTemp = pNode;
            pNode = pNode->pNext;
            delete pTemp;
            nLen --;
        }

        delete pNode;
        nLen --;
    }

    Node<T>* ListHead()
    {
        return m_pHead;
    }

    int ListLength()
    {
        return nLen;
    }
    
private: 
    Node<T>* m_pHead;
    int nLen;
};

View Code

三 约瑟夫问题

(1)何为约瑟夫问题

  据说著名犹太历史学家 Josephus 有过以下的故事:在罗马人占领乔塔帕特后,39 个犹太人与Josephus及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,由第1个人开始报数,每报数到第3人该人就必须自杀,然后再由下一个重新报数,直到所有人都自杀身亡为止。然而 Josephus 和他的朋友并不想遵从,Josephus 要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,于是逃过了这场死亡游戏。

数据结构之循环链表建议收藏

  以上就是著名的约瑟夫问题:N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下Q个。从围成一圈这里就启发了我们可以使用循环链表来解决该问题。

(2)代码实现

void JosephusTest()
{
    int n,m;
    cout << "约瑟夫问题:" << "N个人围成一圈,从第一个开始报数,第M个将被杀掉,最后剩下Q个" << endl;
    cout << "请输入数字N:";
    cin >> n;
    cout << "请输入数字M:";
    cin >> m;

    CircList<int> cirllist;
    cirllist.InitList();
    for (int i = 0; i < n; i ++)
    {
        cirllist.AddNode(i + 1);
    }
    cout << "所有参与人员:";
    cirllist.PrintList();
    cout << endl;
    cout << "-------------------" << endl;

    Node<int>* pListHead = cirllist.ListHead();
    Node<int>* pStartNode = pListHead;
    Node<int>* pTemp = NULL;
    int nListLen = cirllist.ListLength();
    while(nListLen >= m)
    {
        for (int j = 1; j < m; j ++)
        {
            if (pStartNode == pListHead)
            {
                pStartNode = pStartNode->pNext;
            }
            pStartNode = pStartNode->pNext;
        }

        if (pStartNode == pListHead)
        {
            pStartNode = pStartNode->pNext;
        }
        pTemp = pStartNode;
        pStartNode = pStartNode->pNext;
        cirllist.DeleteNode(pTemp->data);
        nListLen --;
        cout << "剩余报数人员:";
        cirllist.PrintList();
        cout << endl;
    }
}

void main()
{
    JosephusTest();
    return;
}

数据结构之循环链表建议收藏

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120157.html原文链接:https://javaforall.net

(0)
上一篇 2021年12月19日 下午3:00
下一篇 2021年12月19日 下午3:00


相关推荐

  • pycharm搭建python环境_pycharm如何配置编译环境

    pycharm搭建python环境_pycharm如何配置编译环境1.安装python27双击执行python-2.7.15.msi,选择装到根目录,建议d:\Python27。一路下一步,直到完成。安装完成之后,打开cmd,输入:python,如果显示以下内容则说明安装python成功如果提示命令不存在则需要设置环境变量。windows:右键我的电脑–属性–高级系统设置–高级–环境变量–系统变量找到path项,加上值,D:\Python27;D:\P…

    2022年8月25日
    12
  • 分苹果_分苹果编程

    分苹果_分苹果编程分苹果时间限制:1000 ms | 内存限制:65535 KB难度:2描述把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(注意:假如有3个盘子7个苹果,5,1,1和1,5,1是同一种分法。)输入t,表示测试组数(t输出输出不同的分法样例输入173样例输出8

    2022年10月12日
    4
  • jwt解析网站_jwt工作原理

    jwt解析网站_jwt工作原理1.Token与Session优缺点概述1.1Session的由来在登录一个网站进行访问时由于HTTP协议是无状态的就是说一次HTTP请求后他就会被销毁,比如我在www.a.com/login里面登录了,然后你就要访问别的了比如要访问www.a.com/index但是你访问这个网站你就得再发一次HTTP请求,至于说之前的请求跟现在没关,不会有任何记忆,这次访问会失败,因为无法验证你的身份。所以你登录完之后每次在请求上都得带上账号密码等验证身份的信息,但是你天天这么带,那太麻烦了。那还可以这样,把我第一

    2022年10月17日
    7
  • jsoup 1.5.2 发布,超棒的 HTML 解析器

    jsoup 1.5.2 发布,超棒的 HTML 解析器

    2021年8月10日
    63
  • spss分析方法-聚类分析

    spss分析方法-聚类分析聚类分析是根据研究对象的特征 按照一定标准对研究对象进行分类的一种分析方法 下面我们主要从下面四个方面来解说 一 实际应用聚类分析的目标就是在相似的基础上收集数据来分类 聚类源于很多领域 包括数学 计算机科学 统计学 生物学和经济学 在不同的应用领域 很多聚类技术都得到了发展 这些技术方法被用作描述数据 衡量不同数据源间的相似性 以及把数据源分类到不同的簇中 商业上 聚类分析被用来发现不同的客户群 并且通过购买模式刻画不同的客户群的特征 聚类分析是细分市场的有效工具 同时也可用于研究消费者行为

    2026年3月19日
    2
  • 数据库的存储过程_数据库的存储过程语句

    数据库的存储过程_数据库的存储过程语句一、存储过程与函数的区别:1.一般来说,存储过程实现的功能要复杂一点,而函数的实现的功能针对性比较强。2.对于存储过程来说可以返回参数(output),而函数只能返回值或者表对象。3.存储过程一

    2022年8月5日
    11

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号