数据结构--链表的排序详解

链表排序——归并排序、快速排序 目录 1 归并排序 1.1 实现思路 1.2 代码实现 2 快速排序 2.1 实现思路 2.2 代码实现 1 归并排序 归并排序基本原理https://blog.youkuaiyun.com/qq_28114615/article/details/86345717 1.1 实现思路        与数组归并排序相同,主要分为以下三个步骤:       ①找到链表中点。最常用的方法是双指针... 阅读详情

1、前言 
前面两篇博客,我已经把线性表的两种基本的表示形式,做了一个基本的介绍和一些对比。但是,我突然发现在链表这里我缺少一个很重要的内容,那就是对我们的链表进行排序,其实,在连接两个链表的时候,就要求我们的那两个链表是有序的。

2、链表排序—最简单、直接的方式(直接采用冒泡或者选择排序,而且不是交换结点,只交换数据域)
 

//线性表的排序,采用冒泡排序,直接遍历链表
void Listsort(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //作为一个临时量
    Node * p;
    Node * p1;
    //如果链表为空直接返回
    if (head->value == 0)return;

    for (i = 0; i < head->value - 1; i++) {
        L = head->next;
        for (j = 0; j < head->value - i - 1; j++) {
            //得到两个值
            p = L;
            p1 = L->next;
            //如果前面的那个比后面的那个大,就交换它们之间的是数据域
            if (p->value > p1->value) {
                Elemtype temp = p->value;
                p->value = p1->value;
                p1->value = temp;
            }
            L = L->next;
        }
    }
}

因为排序中速度比较快的如快速排序是要求它们的数据域的地址是相连接的,它比较适合于顺序结构,而链式结构的时候,我们就只有使用只会进行前后两个比较多排序算法,比如冒泡排序等。我们这里是没有交换结点的一种排序方式,这种方式简单,明了,这样就是数组排序的时候是一样的。后面我会写通过交换结点的方式的排序。 
下面我们就讨论讨论这个排序算法的时间复杂度了,因为它是使用冒泡排序的,它的时间只要消耗在那两重循环,所以时间复杂度为:O(n*n),这个效率实在是太低,下面我们对这个想(ˇˍˇ) 想~通过另外一种方式来实现链表的排序

3、另外一种链表排序方式 
我们在讨论排序算法的时候,都是把数据存放在数组中进行讨论的,在顺序结构下,我们可以采取很多高效的排序算法,那么这个就是我们另外一种对链表排序的方式,先把链表的内容存放到数组中(时间为O(n)),然后,我们在对那个数组进行排序(最快为nlog(n)),最后,存放链表中(时间为O(n))。通过计算,我们可以得到它的时间复杂为(O(nlogn)),这个速度已经和顺序结构下差不多了,可以接受。
 

void Listsort_1(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //如果链表为空直接返回
    if (head->value == 0)return;
    Elemtype * copy = new Elemtype[head->value];
    //变量链表,存放数组
    for (i = 0; i < head->value; i++) {
        L = L->next;
        copy[i] = L->value;
    }
    //调用STL中的sort函数
    sort(copy, copy + head->value);
    L = head;
    //存放回链表中
    for (i = 0; i < head->value; i++) {
        L = L->next;
          L->value= copy[i];
    }
}

4、先我们通过采取增大数据量的方式,比较两种排序在效率如何

è¿éåå¾çæè¿°

 

如图所示,在数据量为10000的时候,明显第二种排序算法消耗的时间比第一种快了28倍左右。

5、下面通过交换结点实现链表的排序 
首先我们编写交换结点的函数,结点的交换主要就是考虑结点的指针域的问题,其中相邻两个结点是一种特殊的情况,要拿出来特别考虑。我们先画出结点交换的思路图,如下图 
首先我们给出相邻两个结点交换的思路: 
 

è¿éåå¾çæè¿°

下面是普通情况下的交换如下图 

è¿éåå¾çæè¿°

 

//参数为头结点和需要交换的两个结点的位置(起点为1)
void swap_node(Node * & head,int i,int j) {
    //位置不合法
    if (i<1 || j<1 || i>head->value || j >head->value) {
        cout << "请检查位置是否合法" << endl;
        return;
    }
    //同一个位置不用交换
    if (i == j)
    {
        return;
    }
    //相邻两个交换比较简单
    if (abs(i - j) == 1) {
        //位置靠前的那个结点的前一个结点
        Node * pre;
        if (i < j)
            pre = getitem(head, i);
        else
            pre = getitem(head, j);

        //保存第一个结点
        Node * a = pre->next;
        //保存第二结点
        Node * b = a->next;
        //改变pre下一个结点的值
        pre->next = b;
        //必须先把b的下一个结点值给a先
        a->next = b->next;
        //让b的下一个结点等于a
        b->next = a;
        return;
    }

    //第一个结点前一个结点
    Node * a = getitem(head, i);
    //第二个结点的前一个结点
    Node * b = getitem(head, j);
    //第一个结点
    Node * p = a->next;
    //第二个结点
    Node * q = b->next;
    //第一个结点的下一个结点
    Node * p_next = p->next;
    //第二结点的下一个结点
    Node * q_next = q->next;

    //a的下一个结点指向第二个结点q
    a->next = q;
    //第二结点的下一个结点指向第一个结点的下一个结点
    q->next = p_next;
    //b的下一个结点指向第一个结点p
    b->next = p;
    //第一个结点的下一个结点指向第二个结点的下一个结点
    p->next = q_next;

}

 排序时候的代码,切记交换结点都是前后结点交换,所以交换完成后,L就已经被移动到下一个结点了,故不要再执行:L=L->next

 

//线性表的排序,交换结点
void Listsort_Node(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //作为一个临时量
    Node * p;
    Node * p1;
    //如果链表为空直接返回
    if (head->value == 0)return;
    int flag = 0;
    cout << head->value << endl;
    for (i = 0; i < head->value - 1; i++) {
        L = head->next;
        for (j = 0; j < head->value - 1 - i; j++) {
            //如果我们交换了结点,那么我们就已经在交换结点的时候,把L移动到下一个结点了,所以不要
            //再执行:L = L->next;,否则会报错的
            if (L->value > L->next->value) {
                flag = 1;
                swap_node(head, j + 1, j + 2);

            }
            if (flag == 1) {
                flag = 0;
            }
            else {
                L = L->next;
            }

        }   
    }
}

好了,今天的就写到这里了,今天通过写交换结点,发现链表真的很容易忽悠人,我就被忽悠了一个小时,才知道那个结点已经被移动到下一个结点了。

最后,补充一个实现链表反转的好方法(感觉你在头文件里面计算一下链表的长度可以带来很多遍历的)

 

void rollback(Node * & head) {
    //先知道了最后一个元素和第一个元素的位置
    int end = head->value;
    int start = 1;
    //两边同时开工
    //进行调换
    while (1) {
        if (end == start)
            return;
        swap_node(head, end, start);
        --end;
        ++start;
    }
}

希望大家,对我写的代码做出一些评价。我想想还是直接贴个完成的代码出来好了,调转代码也在里面了

 

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<windows.h>
#include<algorithm>
using namespace std;
typedef int Elemtype;

//链式结构,我们打算在链表中添加一个
//保存长度的头结点,加入这个结点可以方便我们对结点做一些
//基本的操作,结点保存的是线性表的长度
struct Node
{
    //结点的值,如果是头结点,保存是链表的长度
    Elemtype value;
    //下一个结点的地址
    Node * next;

};

//创建一个空链表,每个头结点就代表一个链表
void InitList(Node * & head) {
    head = new Node();
    head->value = 0;
    head->next = NULL;
}
//销毁一个链表
void DestroyList(Node * & head) {
    delete head;
    head = NULL;
}

//清空整个列表
void ClearList(Node * & head) {
    head->value = 0;
    head->next = NULL;
}

//插入函数
bool Listinsert(Node * & head, int i, Elemtype value) {

    //插入到前面的方法
    int j = 0;
    Node * L = head;
    //如果插入的位置不合法,直接返回错误提示
    if (i<1 || i>head->value + 1)return false;

    //得到插入位置的前一个结点
    while (j < i - 1) {
        L = L->next;
        ++j;
    }

    //s是一个临时结点
    Node * s = new Node();
    s->value = value;    //先对临时结点赋值
    s->next = L->next;   //让临时结点下一个位置指向当前需要插入前一个结点的下一个位置
    L->next = s;          //让前一个结点下一个位置指向临时结点,完成
                          //线性表的长度加一
    ++head->value;
    return true;
}
//得到某个位置上的值
Node * getitem(Node * & head, int i) {
    //我们要求程序返回特定位置上的值
    //我们一样是从头结点开始寻找该位置
    int j = 0;
    Node * L = head;
    //想要的那个位置是否合法
    if (i<1 || i >head->value)return NULL;

    //同样是先得到前一个结点
    while (j < i - 1) {
        L = L->next;
        ++j;
    }
    //value = L->next->value;
    return L;
}
//线性表的排序,采用冒泡排序,直接遍历链表
void Listsort(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //作为一个临时量
    Node * p;
    Node * p1;
    //如果链表为空直接返回
    if (head->value == 0)return;

    for (i = 0; i < head->value - 1; i++) {
        L = head->next;
        for (j = 0; j < head->value - i - 1; j++) {
            //得到两个值
            p = L;
            p1 = L->next;
            //如果前面的那个比后面的那个大,就交换它们之间的是数据域
            if (p->value > p1->value) {
                Elemtype temp = p->value;
                p->value = p1->value;
                p1->value = temp;
            }
            L = L->next;
        }
    }
}
//通过数组来完成我的排序
void Listsort_by_array(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //如果链表为空直接返回
    if (head->value == 0)return;
    Elemtype * copy = new Elemtype[head->value];
    //变量链表,存放数组
    for (i = 0; i < head->value; i++) {
        L = L->next;
        copy[i] = L->value;
    }
    //调用STL中的sort函数
    sort(copy, copy + head->value);
    L = head;
    //存放回链表中
    for (i = 0; i < head->value; i++) {
        L = L->next;
        L->value = copy[i];
    }
}

//参数为头结点和需要交换的两个结点的位置(起点为1)
void swap_node(Node * & head,int i,int j) {
    //位置不合法
    if (i<1 || j<1 || i>head->value || j >head->value) {
        cout << "请检查位置是否合法" << endl;
        return;
    }
    //同一个位置不用交换
    if (i == j)
    {
        return;
    }
    //相邻两个交换比较简单
    if (abs(i - j) == 1) {
        //位置靠前的那个结点的前一个结点
        Node * pre;
        if (i < j)
            pre = getitem(head, i);
        else
            pre = getitem(head, j);

        //保存第一个结点
        Node * a = pre->next;
        //保存第二结点
        Node * b = a->next;
        //改变pre下一个结点的值
        pre->next = b;
        //必须先把b的下一个结点值给a先
        a->next = b->next;
        //让b的下一个结点等于a
        b->next = a;
        return;
    }

    //第一个结点前一个结点
    Node * a = getitem(head, i);
    //第二个结点的前一个结点
    Node * b = getitem(head, j);
    //第一个结点
    Node * p = a->next;
    //第二个结点
    Node * q = b->next;
    //第一个结点的下一个结点
    Node * p_next = p->next;
    //第二结点的下一个结点
    Node * q_next = q->next;

    //a的下一个结点指向第二个结点q
    a->next = q;
    //第二结点的下一个结点指向第一个结点的下一个结点
    q->next = p_next;
    //b的下一个结点指向第一个结点p
    b->next = p;
    //第一个结点的下一个结点指向第二个结点的下一个结点
    p->next = q_next;

}
//反转
void rollback(Node * & head) {
    //先知道了最后一个元素和第一个元素的位置
    int end = head->value;
    int start = 1;
    //两边同时开工
    //进行调换
    while (1) {
        if (end <= start)
            return;
        swap_node(head, end, start);
        --end;
        ++start;
    }
}
void print(Node * & head);
//线性表的排序,采用冒泡排序,直接遍历链表
//线性表的排序,交换结点
void Listsort_node(Node* & head) {
    int i = 0;
    int j = 0;
    //用于变量链表
    Node * L = head;
    //作为一个临时量
    Node * p;
    Node * p1;
    //如果链表为空直接返回
    if (head->value == 0)return;
    int flag = 0;

    for (i = 0; i < head->value - 1; i++) {
        L = head->next;
        for (j = 0; j < head->value - 1 - i; j++) {
            //如果我们交换了结点,那么我们就已经在交换结点的时候,把L移动到下一个结点了,所以不要
            //再执行:L = L->next;,否则会报错的
            if (L->value > L->next->value) {
                flag = 1;
                swap_node(head, j + 1, j + 2);

            }
            if (flag == 1) {
                flag = 0;
            }
            else {
                L = L->next;
            }

        }   
    }
}

void print(Node * & head) {
    //输出我们只需要传入头结点,然后循环判断当前结点下一个结点是否为空,
    //这样就可以输出所有内容
    Node * L = head;
    while (L->next) {
        L = L->next;
        cout << L->value << " ";
    }
    cout << endl;
}
int main() {
    //链表的头结点,不存放任何值,首先初始化头结点
    Node * head;

    Node * head_array;
    Node * head_node;
    Node * head_roll;
    srand((int)time(NULL));     //每次执行种子不同,生成不同的随机数
    //创建一个链表

    InitList(head); 
    InitList(head_array);
    InitList(head_node);
    InitList(head_roll);

    int i;
    cout << "请输入需要插入元素个数" << endl;
    int n;
    cin >> n;//5
    //cout << "请输入" << n << "个值" << endl;
    for (i = 0; i < n; i++) {
        Elemtype temp;
        temp = rand();
        if (!Listinsert(head, i + 1, temp)) {
            cout << "插入元素失败" << endl;
        }
        if (!Listinsert(head_array, i + 1, temp)) {
            cout << "插入元素失败" << endl;
        }
        if (!Listinsert(head_node, i + 1, temp)) {
            cout << "插入元素失败" << endl;
        }
        if (!Listinsert(head_roll, i + 1, temp)) {
            cout << "插入元素失败" << endl;
        }

    }
    cout << "初始化结果" << endl;
    print(head);
    cout << "反转结果" << endl;
    rollback(head_roll);
    print(head_roll);
    cout << "冒泡排序(数据域交换)" << endl;
    Listsort(head);
    print(head);
    cout << "借数组为媒介进行排序(数据域交换)" << endl;
    Listsort_by_array(head_array);
    print(head_array);
    cout << "冒泡排序(结点交换)" << endl;
    Listsort_node(head_node);
    print(head_node);
    system("pause");
    return 0;

}

运行环境:vs2015 
输出结果: 
 

è¿éåå¾çæè¿°


来源: https://blog.youkuaiyun.com/qq_35644234/article/details/53222603 

链表排序算法(C++):数组辅助排序、插入排序、归并排序 阅读详情

相关推荐

Java语言的链表排序

链表的排序是数据结构与算法中一个重要的主题。本文介绍了在Java中对链表进行排序的多种算法,包括选择排序、插入排序、归并排序和快速排序。尽管选择和插入排序容易实现,但在处理大规模数据时,归并排序的性能更佳。通过本文的学习,相信读者在实际开发中能够灵活运用不同的排序算法来优化链表的处理,达到高效的数据存储与管理。希望大家在今后的学习和工作中能够加深对链表排序的理解与实践。

2501_91409228的博客 642

链表排序总结(全)(C++)

文章目录链表排序与数组排序的区别借助外部空间冒泡排序插入排序归并排序快速排序 链表排序与数组排序的区别 数组的排序几乎所有人都很熟悉了,常用的算法插入、冒泡、归并以及快排等都会或多或少依赖于数组可以在O(1)时间随机访问的特点。 链表排序一般指单链表排序,链表是不支持随机访问的,需要访问后面的节点只能从表头顺序遍历,所以链表的排序是一个相对比较复杂的问题。 那么怎样进行链表排序呢? 借助外部空间 既然数组排序简单,那可以借助数组进行排序: 把链表中的值一次遍历导入数组(时间复杂度O(n)) 对数组进行排序

zj 2万+

【数据结构】C++用链表实现一个箱子排序附源代码详解

01 箱子排序 1.1 什么是分配排序? 分配排序的基本思想:排序过程无须比较关键字,而是通过&quot;分配&quot;和&quot;收集&quot;过程来实现排序.它们的时间复杂度可达到线性阶:O(n)。 1.2 什么是箱子排序? 箱子排序是分配排序的一种,箱子排序也称桶排序(Bucket Sort),其基本思想是:设置若干个箱子,依次扫描待排序的记录 R[0],R[1],…,R[n-1],把关键字等于 k 的记录全都装入到第 k ...

infinitor的博客 355

数据结构之链表操作详解与示例(反转链表,合并链表,旋转链表,对链表排序)

本文介绍了链表的四种常见操作:反转链表、合并链表、旋转链表和对链表排序。每种操作都有其特定的应用场景和算法步骤,通过示例代码展示了如何实现这些操作。理解和掌握这些链表操作对于深入理解数据结构和算法至关重要。

qq_35320456的博客 1348

Localizing LabVIEW Application to Different Languages

本文探讨了LabVIEW应用程序的多语言本地化实现方案。文章首先分析了LabVIEW对多语言的支持现状,指出其默认仅支持ANSI编码,对Unicode支持有限,且仅适配中英法德日韩六种语言。然后重点介绍了JKISimpleLocalization工具包的使用方法,该工具能导出/导入JSON词典文件,实现界面语言的实时切换。文章还结合实际工程案例,分析了该方案的局限性:部分控件不可翻译、切换速度较慢(33个界面需50秒)、小语种支持不足等。最后提供了完整的应用流程和工具包附件,包括词典文件转换工具和工程案例。

2301_80383260的博客 1409

刚入职,软件测试岗,有点迷茫不知道下一步怎么提升自己

软件测试前景和发展都是不错,已经入了软件测试这行业就坚挺下去

大白的博客 2219

【数据结构】链表实现冒泡排序 —— C++详解

【数据结构】链表实现冒泡排序 —— C++详解

枯木何日可逢春 949

VASPKIT绘制平面平均电荷差分密度

平面平均密度差(planar-averaged electron density difference)是密度差的衍生。密度差是个三维空间函数,经常通过绘制平面图、等值面图方式图形化考察。虽然这两种图很直观,但平面图会受到截面选取的影响,而等值面图会受到等值面数值(isovalue)选取的影响,因此都有一定任意性,也不容易定量讨论。对于电子转移有比较明确方向的情况,可以绘制平面平均密度差曲线,由此可以清楚地考察垂直于选取的方向上每个截面上的密度差积分值,在定量讨论、对比上比较便利。

weixin_43948934的博客 1万+

【数据结构】链表实现直接插入排序 —— C++详解

【数据结构】链表实现直接插入排序 —— C++详解

枯木何日可逢春 1040

AUTOSAR系统服务篇 - BswM的使用

本文档是对4.0.3版及更高版本的AUTOSAR模式管理应用的介绍。其主要目的是为AUTOSAR的用户和开发人员提供基于示例的AUTOSAR模式管理不同方面的详细概述,这些示例在文中进行了解释。本文中的代码清单共同构成了示例ECU的配置。第2章解释了基础的模式管理概念,例如一般的模式、如何实现模式切换、模式管理者和模式用户的角色等。其次介绍了应用模式管理和基础软件模式管理的依赖关系,两者密切相关。基础软件模式管理器是AUTOSAR R4.0中的中央模式管理模块。它具有很高的可配置性。

IOT2017的博客 847

go实现MQTT broker(附完整源码)

go实现MQTT broker(附完整源码)

希望我的博客,能帮上你解决学习中工作中所遇到的问题 577

java 链表插入排序_javascript数据结构之双链表插入排序实例详解

本文实例讲述了javascript数据结构之双链表插入排序实现方法。分享给大家供大家参考,具体如下:数组存储前提下,插入排序算法,在最坏情况下,前面的元素需要不断向后移,以便在插入点留出空位,让目标元素插入。换成链表时,显然无需做这种大量移动,根据每个节点的前驱节点“指针”,向前找到插入点后,直接把目标值从原链表上摘下,然后在插入点把链表断成二截,然后跟目标点重新接起来即可。双链表-插入排序//节...

weixin_42517987的博客 216

面试真题集(十六):TensorRT基础

TensorRT面试真题解析:从模型优化到推理部署 本文精选了14道TensorRT面试题,涵盖选择题、简答题和场景题,深度考察推理工程师对TensorRT核心技术的理解。内容聚焦三个关键维度: 基础概念 FP16推理中Softmax层为何需保持FP32(数值稳定性) INT8校准原理(EntropyCalibrator2的鲁棒性优势) Plugin V3接口的构建/运行分离设计 性能优化 Conv-BN-ReLU融合减少40-60%延迟的关键机制(访存优化) 动态Shape配置策略(min/opt/max

PeterPan的博客 71

链表大小排序方法c语言,C语言数据结构 链表与归并排序实例详解

C语言数据结构 链表与归并排序实例详解归并排序适合于对链表进行原址排序,即只改变指针的连接方式,不交换链表结点的内容。归并排序的基本思想是分治法:先把一个链表分割成只有一个节点的链表,然后按照一定顺序、自底向上合并相邻的两个链表。只要保证各种大小的子链表是有序的,那么最后返回的链表就一定是有序的.归并排序分为分割和合并两个子过程。分割是用递归的方法,把链表对半分割成两个子链表;合并是在递归返回(回...

weixin_39638647的博客 641

YOLOv8/v9 遥感图像目标检测实战指南:建筑物检测与变化监测

遥感图像在城市规划、灾害评估、农业监管等领域应用广泛,但传统目标检测方法存在效率低、精度不足、难以适配遥感图像大尺寸、多尺度目标等问题。本文以“建筑物检测与变化监测”为核心,基于DOTA、NWPU VHR-10等公开数据集,系统讲解YOLOv8/v9在遥感图像中的实战流程。从数据获取、格式转换、模型训练优化,到大图切片推理、建筑物变化监测,全程提供可复现的代码与参数配置。通过针对性优化(旋转增强、切片推理等),模型在NWPU VHR-10数据集上mAP50达0.85以上,可适配卫星影像、无人机航拍等多场景

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 520

TIA protal与SCL从入门到精通(1)——SCL编程入门

SCL语言是由Pascal而生的结构化程序语言,与梯形图相(LAD)比,SCL语言的灵活程度更高,易于编写控制算法。 本教程基于的平台如下 软件:TIA 15.1 CPU 1516 (1)直接创建纯SCL的程序块儿; (2)在LAD/FBD中在插入SCL程序段。 在程序段中直接右击插入即可,但是插入的程序段并不能完全使用SCL语法,GOTO等跳转指令就不能使用。在SCL中一般不能使用绝对地址进...

苦走一口田 7万+

java构建排序双链表,详解java数据结构与算法之双链表设计与实现

在单链表分析中,我们可以知道每个结点只有一个指向后继结点的next域,倘若此时已知当前结点p,需要查找其前驱结点,那么就必须从head头指针遍历至p的前驱结点,操作的效率很低,因此如果p有一个指向前驱结点的next域,那效率就高多了,对于这种一个结点中分别包含了前驱结点域pre和后继结点域next的链表,称之为双链表。本篇我们将从以下结点来分析双链表双链表的设计与实现双链表的主要优点是对于任意给的...

weixin_39792393的博客 343

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

leetcode刷题总结之链表

前言: 今年过年前的任务就是回顾之前的刷过题,然后弄清以前没有弄懂的知识点,最后归纳整理形成自己的体系。因为“学而不思则罔,思而不学则殆”,在比赛或者面试做题时,只有三种情况,会让你不能ak所有题目,这三种情况分别是:sb失误、不会做、状态不佳。然而写总结所要做的是就是将之前的sb失误减小为0,之前不会做的题做熟做透,摸清套路,至于状态嘛,睡好觉兴奋点就是发挥出真正水平呀。 文章目录1、链表2、...

algsup 9765

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

数据结构与算法---链表

经典的链表应用场景,那就是 LRU 缓存淘汰算法 缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的 CPU 缓存、数据库缓存、浏览器缓存等等。缓存的大小有限,当缓存被用满时,哪些数据应该被清理出去,哪些数据应该被保留? 这就需要缓存淘汰策略来决定。常见的策略有三种:先进先出策略 FIFO(First In,First Out)、最少使用策略 LFU(Least Frequently Used)、最近最少使用策略 LRU(Least Recently Used)。 底层

L1ak的博客 343

深度学习工具包 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")

链表_数据结构

Linked List 目录 环形链表知识点补充2019.2.25 000.链表数据结构的实现 876.链表的中点问题 2.两个链表的反向数学相加 445.两个链表数学相加 24.交换链表相邻的点 83.删除有序列表中的重复点 86.分离数组 203.链表结点的删除 328.奇偶链表 817.链表中元素的分部 23.合并k个有序链表 725.将链表按要求进行分块 148.链表排序,这道题很重要 ...

weixin_30764137的博客 79

数据结构与算法之快速排序

(Quick Sort),又称划分交换排序(partition-exchange sort),通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。3、递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。

2401_83641443的博客 694

嵌入式学习——单向链表的排序、双向链表

单向链表中,外循环拿数,只需要拿到尾节点的前一个节点,然后我们需要用两个指针,一个指针来表示每趟循环从首节点开始比,另一个指针记录每次比较结束的位置,这样就可以根据比较的趟数来减少相应的值。在单向链表中,将首节点看作是有序区,将首节点指向NULL,然后从首节点的下一个节点拿数到有序区比较,因为拿的数可能比首节点小,所以我们要从头结点开始比。按照前面数组的排序,我们知道,选择排序是给合适的位置选择合适的数,外循环是用来控制位置,内循环是来找合适的数。

2301_81380359的博客 336

C++链表核心操作:插入、删除与归并排序实现详解

链表作为基础数据结构,通过节点与指针实现动态存储,其核心在于指针操作与内存管理。理解链表原理有助于掌握非连续存储结构,提升算法思维与编程能力。在工程实践中,链表常用于实现队列、栈及内存管理等场景,其插入、删除操作的时间复杂度为O(1),但需注意边界条件与内存安全。本文聚焦链表的核心操作,通过手把手实现插入、删除及归并排序,深入解析指针逻辑与常见陷阱,帮助开发者夯实C++基础,应对技术面试挑战。

weixin_33978044的博客 365

Light Tips揭秘:从链表到堆排序,PHP数据结构完全解析

Light Tips是一个专注于PHP算法与数据结构的开源项目,提供了从基础链表到高级堆排序的完整实现。本文将带你探索这个项目的核心功能,帮助PHP开发者快速掌握数据结构的实际应用技巧。 ## 为什么选择Light Tips学习数据结构? Light Tips项目通过直观的PHP代码实现,将抽象的数据结构概念转化为可直接运行的实例。项目包含丰富的算法实现,从简单的线性表到复杂的树结构,覆盖了面

gitblog_00338的博客 253

剑指offer(十六):合并两个排序的链表 递归方法python版详解

剑指offer(十六)合并两个排序的链表 递归方法递归代码递归详解 最近刷题发现我真是个菜鸡,看书人家都说这道题hen简单我们这样这样就好然后直接贴代码,奈何我这样都看不懂,尤其是有的题的递归解法,我全是啥玩意儿啊?咋回事儿啊??所以自己画画图给自己康康… 递归代码 class Solution: # 返回合并后列表 def Merge(self, pHead1, pHead2):...

qq_41716831的博客 433
上一篇: 码农翻身精华文章
下一篇: 面对不稳定的百度网盘离线下载,这些备用方案可以帮你应急
Estrellas_
博客等级 码龄9年 273粉丝 233原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值