链表-双向链表

双向循环链表的讲解及实现(图解+代码/C语言) 本文主要分享了双向循环链表(带头)的写法,使用C语言完成,文中附有具体的结构图片帮助大家理解,希望对大家有帮助 阅读详情

一、双向链表

1.单向链表的缺点分析:

1、单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找
2、单向链表不能自我删除,需要靠辅助结点,而双向链表则可以自我删除。

2、双向链表的遍历、增删改查操作

① 遍历:和单链表一样,只是可以向前,也可以向后
② 增加:(默认添加到双向链表的最后)
1)先找到双向链表的最后结点
2)temp.next=newHeroNode;
3) newHeroNode.pre=temp;
③ 修改:思路和单向链表一样
④ 删除:可以自我删除某个结点
1)先找到想要删除的这个结点
2)temp.pre.next=temp.next;
3) temp.next.pre=temp.pre;

3.结点类的创建,双向链表类的创建、功能实现:

① 结点类的创建,代码如下:

// 定义HeroNode2,每个HeroNode2的实例对象就是一个结点
class HeroNode2{
    public int no;
    public String name;
    public String nickname;
    public HeroNode2 next;  // 指向下一个结点
    public HeroNode2 pre;   // 指向上一个结点

    public HeroNode2(int no, String name, String nickname) {
        this.no = no;
        this.name = name;
        this.nickname = nickname;
    }

    // 为了显示方便,重写toString方法
    @Override
    public String toString() {
        return "HeroNode{" +
                "no=" + no +
                ", name='" + name + '\'' +
                ", nickname='" + nickname + '\''  +
                '}';
    }
}

② 双向链表类的创建、功能实现 代码如下:

// 创建一个双向链表的类
class DoubleLinkedListt {
    // 先初始化一个头结点,头结点不要动,不存放具体数据
    private HeroNode2 head = new HeroNode2(0, "", "");

    //   返回头结点
    public HeroNode2 getHead() {
        return head;

    }

    // 显示链表【遍历】
    public void showlist() {
        // 判断链表是否为空
        if (head.next == null) {
            System.out.println("链表为空");
            return;
        }
        // 因为头结点,不能动,因此要一个辅助遍历temp来遍历
        HeroNode2 temp = head.next;
        while (true) {
            // 判断是否到链表最后
            if (temp == null) {
                break;
            }
            //输出结点信息
            System.out.println(temp);
            // 将temp后移,一定要小心
            temp = temp.next;

        }
    }

    // 添加操作  按结点编号顺序插入链表中
    public void doubleAdd(HeroNode2 heroNode2){
        boolean flag=false;
        HeroNode2 temp =head;
        while (true){
            if (temp.next==null){
                break;
            }
            if (temp.next.no>heroNode2.no){
                break;
            }
            if (temp.next.no==heroNode2.no){
                flag=true;
                break;
            }
            temp=temp.next;
        }
        if (flag){
            System.out.printf("需要添加的结点编号%d:已存在",heroNode2.no);
        }else {
            if (temp.next!=null){
                temp.next.pre=heroNode2;
                heroNode2.next=temp.next;
                heroNode2.pre=temp;
                temp.next=heroNode2;
            }else {
                temp.next=heroNode2;
                heroNode2.pre=temp;
            }
        }
    }

    // 修改一个结点的内容  与点链表一样
    // 修改节点的信息,根据no编号来修改,即no编号不能改
    // 说明:根据newHeroNode 的no来修改
    public void updata(HeroNode2 newHeroNode2){
        if(head.next==null){
            System.out.println("链表为空");
            return;
        }
        HeroNode2 temp=head.next;
        boolean flag=false;
        while (true){
            if(temp==null) {
                break;  // 到链表的最后 已经遍历完链表了
            }
            if(temp.no==newHeroNode2.no){
                flag=true;  // 找到了
                break;
            }
            temp=temp.next;
        }
        // 根据flag判断是否找到要修改的结点
        if (flag){
            temp.name= newHeroNode2.name;
            temp.nickname=newHeroNode2.nickname;
        }else {
            System.out.printf("没有找到编号%d的结点 ",newHeroNode2.no);
        }
    }

    //根据no值来判断删除  与单链表不同,双链表可以再定位到要删除结点的地方实现自我删除
    public void del(int no){
        if (head.next==null){
            System.out.println("链表为空,无法删除");
            return;
        }

        HeroNode2 temp=head.next;
        boolean flag=false;  //  标识是否找到
        while (true){
            if (temp==null){ //到最后
                break;
            }
            if (temp.no==no) {
                // 找到待删除结点的temp
                flag = true;
                break;
            }
            temp=temp.next; // temp后移,继续遍历
        }
        if (flag){
            temp.pre.next=temp.next;
            // 如果是最后一个结点,就不要执行下面这句话,否则出现空指针异常
            if (temp.next!=null){
                temp.next.pre=temp.pre;
            }

        }else {
            System.out.printf("要删除的编号%d的结点不存在\n",no);
        }
    }
}

③主类测试,代码如下:

public class DoubleLinkedList {
    public static void main(String[] args) {

        // 进行测试
        // 先创建结点
        HeroNode2 sj = new HeroNode2(1, "宋江", "及时雨");
        HeroNode2 ljy = new HeroNode2(2, "卢俊义", "玉麒麟");
        HeroNode2 wy = new HeroNode2(3, "吴用", "智多星");
        HeroNode2 lc = new HeroNode2(4, "林冲", "豹子头");

        // 创建双向链表
        DoubleLinkedListt doubleLinkedList = new DoubleLinkedListt();

        // 结点编号方式添加  (根据no来排列添加)
        doubleLinkedList.doubleAdd(sj);
        doubleLinkedList.doubleAdd(lc);
        doubleLinkedList.doubleAdd(wy);
        doubleLinkedList.doubleAdd(ljy);

        // 显示
        doubleLinkedList.showlist();

        // 修改一个结点
        HeroNode2 gss = new HeroNode2(2, "公孙胜", "入云龙");
        doubleLinkedList.updata(gss);

        System.out.println("修改后的双向链表");
        //修改后显示
        doubleLinkedList.showlist();

        //删除操作
        doubleLinkedList.del(3);

        System.out.println("删除后的双向链表");
        //删除后显示
        doubleLinkedList.showlist();
    }
}

二、单向环形链表以及(约瑟夫问题)

1.构建一个单向环形链表思路

1、先创建第一个结点,让first指向该结点,并形成环形(first不能动,需要辅助变量temp来移动)
2、后面当每创建一个新的结点,就把该结点,加入到已有的环形链表中即可。

遍历单向环形链表
1、先让辅助指针temp(变量),以及指针first指向第一个结点
2、然后通过while循环遍历该环形链表 temp.next==first(表示遍历一圈结束)

2.环形链表的创建的过程

① 创建一个结点类(Person)

// 创建一个Person类表示一个结点
class Person{
    public int no; // 编号
    public Person next; // 指向下一个结点,默认null

    public Person(int no) {
        this.no = no;
    }

    public int getNo() {
        return no;
    }

    public void setNo(int no) {
        this.no = no;
    }

    @Override
    public String toString() {
        return "Person{" +
                "no=" + no +
                '}';
    }
}

② 创建一个环形链表的类,其中先创建一个类似头结点的第一个结点first(作为指针),后续在添加结点的方法中给其指向第一个数据结点

// 创建一个环形链表的类
class CircleSingLinkedList{
    // 创建一个first结点,当前没有编号  // 类似头结点,不过后面要赋值
    // private Person first =null;
    private Person first = new Person(-1);

    //添加结点的方法
    public void CircleAdd(int nums){
        // nums做一个数据校验
        if (nums<1){
            System.out.println("输入的nums的值不正确");
            return;
        }
        Person temp=null;  // 创建辅助变量 temp
        // 使用for来创建我们的环形链表
        for (int i=1;i<=nums;i++){
            // 根据编号,创建person结点
            Person person = new Person(i);
            // 如果是第一个人
            if (i==1){
                first=person;      // 第一个结点first指向新结点,编号1
                first.next=first; // 形成一个元素的环形链表
                temp=first;  // 由于first不能动,让temp辅助变量也指向它来替代
            }else {
                temp.next=person;  // 第一个/添加上一个循环中的person结点指向这一循环中的person
                person.next=first; // 这轮循环中的person结点指向,第一个结点
                temp=person;  // temp后移到这轮循环person结点的位置
            }
        }
    }

    // 遍历环形链表
    public void ShowCircleList(){
        if (first.no==-1){  //没有链表
            System.out.println("没有任何人员");
            return;
        }
        // 因为first不能动,因此我们使用一个辅助指针temp(变量)来完成
        Person temp=first;
        while (true){
            System.out.printf("人员的编号为%d:\n",temp.no);
            if (temp.next==first){
                break;
            }
            temp=temp.next;
        }
    }
}

③ 测试环形链表

public class Josephu {
    public static void main(String[] args) {
        // 测试创建一个环形链表和它的遍历
        CircleSingLinkedList circleSingLinkedList = new CircleSingLinkedList();

        // 加入9个Person成员结点进入链表
        circleSingLinkedList.CircleAdd(9);

        // 遍历显示
        circleSingLinkedList.ShowCircleList();
    }
}

3.约瑟夫问题

约瑟夫问题:设编号为1、2、…n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,以此类推,直到所有人出列为止,由此产生一个出对编号的序列。

例如:

生成9个成员的出圈小队。
n=9,即有9个成员
k=1,从第一个人开始报数
m=2,每次数2下

思路: 此方法由于first没有使用辅助指针,一直在变化,因此链表的结构受到改变
1、需求创建开始报数结点的例如(first)和指向从开始报数的结点的前一个结点位置的一个辅助指针helper
补充:报数前,先让first和helper移动k-1次
2、当成员报数时,让开始报数的结点和helper指针同时移动m-1次
3、这时就可以将temp指向的小孩结点出圈
first=first.next (first要后移一位)
helper.next=first (helper没有移动,只是它的指向)
原来的first指向的结点就没有任何引用,就会被自动回收

//

根据用户的输入,计算出成员出圈的顺序

/*
 * startNo 表示从第几个成员开始报数
 * countNum 表示数几下
 * nums 表示最初有多少个成员在圈中
 * */

代码如下:

public void countPerson(int startNo,int countNum ,int nums){
        // 先进行数据校验
        if (first==null || startNo<1 || startNo>nums){
            System.out.println("参数输入有误,请重新输入...");
            return;
        }
        // 创建辅助指针,帮助出圈   因为直接移动first,helper的存在保证一直是个环形链表
        Person helper = first;
        // 需求创建一个辅助指针(变量)helper,事先应该指向环形链表最后的结点
        while (true){
            if (helper.next==first){
                break;
            }
            helper=helper.next;
        }
        // 成员报数前,先让first和helper移动k-1次
        for (int j=0;j<startNo-1;j++){
            first=first.next;
            helper=helper.next;
        }
        // 当成员报数时,让first和helper指针同时移动m-1次,然后出圈
        // 这里是一个循环操作,直到圈中只有一个结点
        while (true){
            if (helper==first){
                break;   //圈中只有一个结点
            }

            // 让first和helper指针同时移动到 countNum-1
            for (int j=0;j<countNum-1;j++){
                first=first.next;
                helper=helper.next;
            }

            // 这时first指向的结点,就是要出圈的成员结点
            System.out.printf("成员%d出圈\n",first.no);
            // 这时将first指向的成员结点出圈
            first=first.next;   // first要后移一位
            helper.next=first; //  helper没有移动,只是它的指向
        }
        System.out.printf("最后留在圈中的成员编号%d\n",first.no);
    }

测试如下:

// 测试成员出圈
        circleSingLinkedList.countPerson(1,2,5);
数据结构——带头节点的双向循环列表 注意,在带头节点的双向循环链表中,头结点的 next 指针不再指向第一个实际节点,而是指向链表中的第一个节点。注意,在带头节点的双向循环链表中,头结点的 next 指针不再指向第一个实际节点,而是指向链表中的第一个节点。函数的参数是指向链表头结点的指针 plist 和要查找的数据 x,函数返回找到的节点的指针,如果未找到则返回 NULL。是一种特殊的双向链表,它与普通的双向链表相比,最大的区别是链表头结点的 next 指针不再指向第一个实际节点,而是指向链表中的第一个节点。 阅读详情

相关推荐

数据结构-链表结构-双向链表

双向链表

陆卿之的博客 4462

线性表--双向链表

双向链表:相比于单链表,双向链表有两个指针域,既可以保存右边的节点地址(后继),也可以保存左边的节点地址(前驱)。如果指针域指向一个不存在的节点,则将其指针置为NULL。 。

小程的博客 1492

C++实现单向链表,双向链表,单向环形链表,双向环形链表

本文讲解了链表的四种类型以及数据结构,同时给出了四种链表的C++代码实现。

ttug22的博客 1382

【数据结构】双向链表的遍历、添加、修改和删除

双向链表的遍历、添加、修改和删除 (1)单向链表,查找的方向只能是一个方向,而双向链表可以向前或者向后查找。 (2)单向链表不能自我删除,需要靠辅助节点,而双向链表,则可以自我删除。

dengmsjava的博客 2934

【编号326】全国地灾数据全国25万多个地质灾害点空间分布数据

全国地质灾害点分布数据涵盖25万多个各类灾害点信息,为灾害防治提供重要依据。通过分析灾害分布规律,可识别高风险区,指导监测预警、应急避险和基础设施建设。多地成功案例(如湖北兴山崩塌避险、重庆长寿滑坡预警、湖南"挪床行动")证明,提前预警和科学防治能有效避免人员伤亡。云南省2024年通过预警体系成功避让31起灾害,保护1342人生命安全。这些实践表明,地质灾害防治需结合科技手段与群防体系,实现早预警、早处置。

千奇百怪无奇不有 1467

【正点原子STM32连载】第六十章 串口IAP实战:从Bootloader到APP的无缝升级

本文以正点原子STM32F103开发板为例,详细讲解了串口IAP(在应用编程)技术的实现原理与实战步骤。内容涵盖Bootloader与APP的分工、FLASH空间规划、核心代码解析以及Ymodem协议的应用,旨在帮助开发者掌握通过串口为嵌入式设备实现远程固件升级的关键技术,提升产品维护与迭代效率。

weixin_29161719的博客 444

双向链表

为什么需要双向链表? 单链表的结点都只有一个指向下一个结点,单链表的数据元素无法直接访问其前驱元素,所以逆序访问单链表中元素极其耗时; 思想有点类似使用空间复杂度换时间复杂度。 双向链表:在单链表的结点中增加一个指向其前驱的pre指针;该链表中第一个结点的前趋结点为NULL,最后一个结点的后继结点为NULL 。 双向链表具有单链表的所有操作:创建、销毁、获取链表长度、清空、获取某个元素、插入...

小童的博客 9949

避坑指南:PyTorch ConvLSTM参数配置的那些坑(hidden_dim/kernel_size/num_layers详解)

本文深度解析PyTorch ConvLSTM中hidden_dim、kernel_size和num_layers三大核心参数的配置技巧,提供实战指南和性能优化建议。通过实验数据揭示参数组合的内在规律,帮助开发者避免常见配置陷阱,提升时空序列建模效果。特别针对视频预测、气象预报等应用场景,给出黄金参数组合方案和调试技巧。

vv45678的博客 700

双向链表详解

4.newnode有两个指针,它现在是新的尾结点,所以她的next指针指向头结点phead,它的prev指针指向前一个节点也是就phead->prev指向的节点,那原来的尾结点的next指针也要改变,改完指向下一个节点也就是newnode,头结点的prev指针也要改变,现在它指向新的尾结点也就是newnode。4.phead->next指针指向的节点的prev指针改变指向,现在指向newnode,phead指向节点的next指针改变指向,现在指向newnode。newnode的prev指针指向phead。

xpcxpt的博客 2364

数据分析面试八股文--技能软件类

数据分析的“三板斧"指的是三个在 Python 数据分析领域广泛使用的库:NumPy,Pandas,和 Matplotlib。这三个库提供了处理和分析数据的强大工具。NumPyNumPy(Numerical Python)是一个开源 Python 库,用于支持大型多维数组和矩阵运算。此外,NumPy 还提供了大量的数学函数来操作这些数组。np.array():创建数组np.arange():返回一个有终点和起点的固定步长的排列。

zfyzfw的博客 4376

AI Agent在智能投研中的实战:多智能体信息整合与策略生成

那么,什么是AI Agent?简单来说,AI Agent是一种能够感知环境、做出决策并采取行动的自主系统。自主性:能够在没有人类直接干预的情况下运行,对自己的行为和内部状态有一定的控制权。反应性:能够感知环境的变化,并及时做出反应。主动性:不仅能够对环境变化做出反应,还能够主动地设定目标并采取行动实现这些目标。社会性:能够与其他Agent(包括人类和人工智能)进行交互、协作和竞争。它们可以全天候不间断地监控和处理海量信息,大大提升信息处理能力;

AI大模型应用之禅 188

什么是双向链表,一篇搞懂双向链表

双向链表,python3

hahaha_1112的博客 1970

图腾柱无桥PFC控制逻辑解析:从双闭环到电压前馈的设计演进

本文深入解析图腾柱无桥PFC控制逻辑的设计演进,从经典双闭环控制到电压前馈技术的实现。通过分析功率波动问题和动态响应慢的症结,提出引入电压前馈的解决方案,并详细探讨数字实现中的关键注意事项。文章还涵盖控制框图的构建、稳定性分析方法及实际应用中的调参技巧,为开关电源设计提供实用指导。

weixin_29268267的博客 570

双向链表的实现

本文主要介绍了双向链表的结构,概念,相关接口的具体实现方法和链表与顺序表的区别, 并简要介绍了哨兵位的含义与作用。

2303_81060385的博客 1243

《HiVT: Hierarchical Vector Transformer for Multi-Agent Motion Prediction》论文阅读之HiVT

目录摘要1.介绍2.相关工作3.方法3.1. 总体框架3.2 场景表示 3.3 分层向量Transformer3.3.1 局部编码器3.3.2 全局交互模块3.3.3 多模态未来解码器3.4 训练4.实验4.1 实验设置4.2 消融研究 4.3. 结果5.结论 准确预测周围交通参与者的未来运动对于自动驾驶车辆的安全至关重要。最近,矢量化方法由于能够捕捉交通场景中的复杂交互而在运动预测领域占据主导地位。然而,现有的方法忽略了问题的对称性并且受到昂贵的计算成本的影响,面临着在不牺牲预测性能的情况

Gavinmiaoc的博客 3338

AEJoy —— 表达式之仅限在某一维摆动【JS】

效果图 wiggle() 的作用仅限于水平方向 想法 wiggle() 确实是一个非常方便的工具,但有时您希望对它有更多的控制。在本例中,我们希望仅将摆动限制在水平方向。 设计 要理解 wiggle() 最重要的一点是,它生成的结果与应用它的属性具有相同的维度。例如,如果你将 wiggle() 应用于 3D 层的 position 属性,结果将是一个由三个元素组成的数组(x、y 和 z 各一个)。我们需要做的就是将 wiggle() 的结果捕捉到一个变量(我们称之为 “w” ),然后从这个变量中提取我们想

ShaderJoy 的兴趣技术杂货铺 2094

【数据结构】之双向链表、双端(双向)链表、循环(双向)链表

双向链表、双端(双向)链表、循环(双向)链表示意(简)图: 声明:下面各图中,箭头指向的是整个节点,而不是指向节点中的prior或next。 双向链表:只有一个指针指向最开始的结点。 双端(双向)链表:有两个指针分别指向两端的节点。 循环(双向)链表:指向形成一个闭环。 双端(双向)链表的Java实现(简单示例): 注:双向链表、双端(双向)链表、循环(双向)链表的实现思路...

JustryDeng 2211

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

数据结构——双向链表(双向连接的图解、双向链表的创建、操作双向链表)

举个例子: 假设一个文本编辑用链表来存储文本. 每一行用一个String对象存储在链表的一个节点中. 当编辑器用户向下移动光标时, 链表直接操作到下一个节点即可. 但是当用于将光标向上移动呢?- 我们可以轻松的到达下一个节点, 但是回到前一个节点是很难的. 但是, 在实际开发中, 经常会遇到需要回到上一个节点的情况。- 也就是链表相连的过程是单向的. 实现的原理是上一个链表中有一个指向下一个的引用.- 一个节点既有向前连接的引用, 也有一个向后连接的引用.- 既可以从头遍历到尾, 又可以从尾遍历到头。

qq_52301431的博客 4575

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

【双向链表】数据结构双向链表的实现

双向链表的实现

m0_56069910的博客 2196

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

第2章 双向链表

对链表而言,双向均可遍历是最方便的,另外首尾相连循环遍历也可大大增加链表操作的便捷性。因 此,双向循环链表,是在实际运用中是最常见的链表形态。

m0_74916669的博客 945

数组实现双向链表、双向链表的操作

分析: 思路: 遍历:和单链表一样,只是可以向前,也可以向后查找。 添加(默认添加到双向链表的最后) (1).先找到双向链表的最后这个节点(temp) (2).temp.next = newHeroNode (3).newHeroNode.pre = temp; 修改思路和单链表一样 删除 (1).以为是双向链表,因此,我们可以实现自我删除某个节点 (2).直接找到要删除的这个节点,比...

qq_40823802的博客 2011

双向链表和双向循环链表

1.创建一个新结点2.遍历链表找到最后一个结点p3.p结点的后继指针指向新结点,新结点的前驱指针指向p,新结点的后继指针指向NULL;void Insert_tail(DLIST head, DLIST node)\\尾部插入= NULL)void Show(DLIST head)\\打印链表while (p!= NULL)int main()\\运行Show(head);return 0;

weixin_63082397的博客 1015

特殊的链表——双向链表

一、双向链表的概述 1、双向链表的定义:在单链表的每个结点里再增加一个指向其直接前驱的指针域prior,这样链表中就形成了有两个方向不同的链,故称为双向链表。 2、优点:双向链表可以克服单链表查找链表中某结点不方便的缺点。 3、双向循环链表:和单链的循环表类似,双向链表也可以有循环表。让头结点的前驱指针指向链表的最后一个结点,让最后一个结点的后继指针指向头结点。 二、双向链表的特点与算法操作 1、双向链表结构的对称性:设指针P指向某一结点,侧有: p->next->prior=p=p

kxbdys的博客 4419

双向链表的双向遍历

双向链表的双向遍历 双向链表相比较于单向链表的优势之一就是可以快速遍历,对于单向链表只能借助于单个指针逐个遍历,而对于双向链表而言因为每个节点都存在一个前指针和后指针,所以可以借助于两个指针双向遍历,相对于单向链表而言可以节省很多时间。但是对于双向链表的双向遍历需要考虑的因素偏多,代码的步骤需要非常严谨。对于两个指针而言需要考虑节点数是奇数还是偶数,若是奇数,要考虑两指针相遇的情况,只需要输出其中...

A___jay的博客 3887
上一篇: 链表-单向链表
下一篇: 栈和栈的应用
AX_Chu
博客等级 码龄6年 13粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值