【数据结构】01 常见数据结构及概述

目录


数据结构与算法密切相关;

参考:

  1. [数据结构]——链表(list)、队列(queue)和栈(stack)
    //讲的很详细 需要仔细看
  2. 《大话数据结构》

1. 基础

//数据结构基础

1.1. 基本概念

1.1.1. 基本概念

  1. 逻辑结构
    数据对象中数据元素之间的相互关系。 //P7
    1. 集合结构:数据元素无相互间的关系;
    2. 线性结构:一对一;
    3. 树形结构:一对多;
    4. 图形结构:多对多;
  2. 物理结构
    即存储结构,数据的逻辑结构在计算机中的存储形式;
    包括顺序存储结构链式存储结构
    1. 顺序存储:地址连续;
    2. 链式存储:存储单元未必连续;

1.1.2. 数据结构 类型概述

  1. 队列(queue):
  2. **栈(stack):**先进后出。按照顺序依次出入
  3. **串(string):**字符串;
  • 注解
    1. 操作对数据的进入和取出顺序有严格要求选择,而且必须是先进后出的。对顺序没有要求的时候可以选用链表。

1.1.3. 线性表

  1. 定义:

  2. 分类:

    1. 顺序存储结构 --普通顺序存储
      1. 无序线性表:插入删除效率尚可;因无序,查找效率太低;
      2. 有序线性表:插入删除耗时;查找速度快(可使用折半、插值、斐波那契等);
        //P314
  3. 链式存储结构

    1. 单链表
    2. 静态链表
    3. 循环链表
    4. 双向链表
  4. 优缺:

1.2. 辨析 //重要

1.2.1. 结构

  1. 线性表
    1. 第一个数据元素:无前驱;
    2. 最后一个:无后继,一个;
    3. 中间元素:前驱、后继各一个;
    1. 根节点:无双亲;
    2. 叶节点:污孩子,可以多个;
    3. 中间节点:一个双亲多个孩子;

1.2.2. 操作类型

  1. 线性表更加关注 单个元素 的操作;例:查找、插入或删除 一个元素。
    栈和队列是特殊的线性表;
  2. :很大的区别于线性表;串中更多的是
    查找子串位置、读取指定位置的子串、替换子串等操作;

2. 链表 List

2.1. 实践使用

  1. 数组与链表
  2. 当需要存储多个相同类型的数据时,优先使用数组。数组可以通过下标直接访问(即随机访问)。
    //数组的优势
  3. 正是由于这个优点,数组无法动态添加或删除其中的元素,而链表弥补了这种缺陷。
    //数组的不足 链表的特点

2.2. 链表详解

2.2.1. 单向链表

单向链表,即只有一个指针,该指针指向下一个元素的地址。通常只要知道链表首地址,则可以遍历整个链表。由于链表节点是在堆区动态申请的,其地址并不是连续的,因此无法进行随机访问,只有通过前一节点的next指针才能定位下一节点的地址。

  1. 代码示例

2.2.2. 双向链表

  1. 优缺

    1. 单向链表只能向后遍历,无法逆序遍历,而使用更广泛的双向链表,即节点内部增加一个字段prev,用以存储该节点的前*一个节点地址。
    2. 双向链表可以双向遍历但仍然只能顺序访问,无法像数组那样随机访问
  2. 双向链表的List实现 //STL实现的双向链表

    1. List是stl实现的双向链表,与向量(vectors)相比,
    2. 允许快速的插入和删除,但是随机访问却比较慢(缺)。
    3. #include //使用时需要添加头文件;
  3. 语法格式

    ------ List定义和初始化:
    list<int>lst1;       //创建空list
    list<int> lst2(5);   //创建含有5个元素的list
    list<int>lst3(3,2);  //创建含有3个元素的list
    list<int>lst4(lst2); //使用lst2初始化lst4
    list<int>lst5(lst2.begin(),lst2.end());      //同lst4
    -------  List常用操作函数:
    Lst1.assign()          给list赋值
    Lst1.back()            返回**最后一个**元素
    Lst1.begin()           返回指向第一个元素的迭代器
    Lst1.clear()        删除所有元素
    Lst1.empty()        如果list是空的则**返回true** //返回值为true
    Lst1.end()          返回末尾的迭代器
    Lst1.erase()        删除一个元素
    Lst1.front()        返回第一个元素
    Lst1.get_allocator()    返回list的配置器
    Lst1.insert()           插入一个元素到list中
    Lst1.max_size()         返回list能容纳的最大元素数量
    Lst1.merge()            合并两个list
    Lst1.pop_back()         删除最后一个元素
    Lst1.**pop**_front()    删除第一个元素
    Lst1.push_back()        在list的**末尾添加**一个元素
    Lst1.push_front()       在list的**头部添加**一个元素
    Lst1.rbegin()        返回指向第一个元素的逆向迭代器
    Lst1.remove()        从list删除元素
    Lst1.remove_if()     按指定条件删除元素
    Lst1.rend()          指向list末尾的逆向迭代器
    Lst1.resize()        改变list的大小
    Lst1.reverse()       把list的元素倒转
    Lst1.size()          返回list中的元素个数
    Lst1.sort()     给list排序
    Lst1.splice()   合并两个list
    Lst1.swap()     交换两个list
    Lst1.unique()   删除list中重复的元素
    

参考:

  1. C++之list的使用总结及常用list操作
    //有具体语法讲解和代码示例
  2. MFC中CList类使用方法
    //双向链表类,实际使用较多

3. 栈 Stack 和 队列 Queue

队列属于特殊的线性表,所以和线性表一样,共有两种存储结构:顺序存储链式存储
//栈(stack)
栈的使用,具体概念、栈的实现;

3.1. 实践使用

概念区分

  1. 堆和栈的区别 之 数据结构和内存 //很重要 必看
    by叫我大侠

  2. 栈数据操作方式 概述 //后进先出 与队列不同之处

    1. 栈的特点与队列正好相反,按照数据入栈顺序逆序出栈,即**“后进先出”**。
    2. 通常会对栈进行频繁入栈和出栈,与队列类似,一般使用定长数组存储栈元素,而不是动态申请节点空间。
    3. 具体进出栈过程
      与队列类似,使用一个结构体存储当前栈的大小和容量。由于入栈和出栈都在栈顶,所以只需要一个size字段存储当前栈的大小。每次入栈时,将size向后移动;出栈时将size向前移动,注意不要超过容量,初始化size为0。
  3. 分为 顺序存储链式存储 两种方式

  4. 栈操作

    1. c++ stl栈stack的头文件为:
      #include
  5. c++ stl栈stack的成员函数介绍

    操作 比较和分配堆栈
    **bool** empty(); //判断是否为空 堆栈为空则返回**真**
    **void** Pop(); 移除栈顶元素
    **void** Push(**const** T & s); 在栈顶增加元素
    **size_t** size(); 返回栈中**元素数目**
    T & Top(); 返回栈顶元素
    
  6. 栈操作参考示例

    1. C++中栈结构建立与操作详细解析
      //含有术语说明和代码
    2. C++实现栈的基本操作
      //
    3. 代码实现栈的各种操作
      //看懂

注意:

  1. 链表、队列和栈的概念介绍完毕,虽然很简单,但是就像数组那样简单而又广泛使用。以上代码均为C风格代码。
  2. C++中,因为STL中已经包含了这三种数据结构,并使用模板类进行书写。其中队列和栈为动态增长的,不必要初始其容量。当需要使用这三种数据结构时,优先使用STL提供的代码,而不是自己动手实现。

3.2. 栈的详解

  1. 分类

    1. 顺序栈:栈的顺序存储结构
      1. 顺序栈的两栈共享空间;
    2. 链栈:栈的链式存储结构;
  2. 后缀表达式与栈的结合

  3. 注意:

    1. 链栈没有头节点;
    2. 栈是在内存中使用;
    3. 顺序栈、链栈:时间复杂度均为O[1];

3.3. 实践使用

  1. 队列数据操作方式 //先进先出
    1. 队列即按照数据到达的顺序进行排队,每次新插入一个节点,将其插到队尾;每次只有对头才能出队列。简言之,对于数据元素的到达顺序,做到“先进先出”。
    2. 由于队列通常频繁的插入与删除,为了高效,一般使用固定长度的数组进行实现,并且可循环使用数组空间,所以要经常处理当前队列是否为满或为空。
    3. 如需要动态长度,可以用链表实现,只需要同时记住链表首地址(队列的头)和尾地址(队列的尾)。

3.4. 队列详解

  1. 定义:
    只允许在 队尾插入,队头删除线性表; //FIFO模式
  2. 分类
    1. 顺序队列:
      1. 循环队列:
    2. 链队列:线性表的单链表+尾进头出;

4. 树 Tree

//大话数据结构 P151

4.1. Tree 概述

  1. 概念

4.2. 二叉树 Binary Tree

5种基本类型;3种特殊二叉树;

4.2.1. Binary Tree 概述

  1. 二叉树特点
    1. 每个节点最多两棵子树;
    2. 左右子树有顺序,不可颠倒;
    3. 区分左右子树,哪怕只有一棵子树;
  2. 特殊二叉树 //P166
    1. 斜树
    2. 二叉树
    3. 完全二叉树
      区分:满二叉树一定是完全二叉树,但完全二叉树不一定是满的;

4.2.2. 遍历 二叉树

//遍历名称针对 根节点 4种主要遍历方法 P174

  1. 前序遍历
    中左右;左到底;
  2. 中序遍历
    左中右;
  3. 后序遍历
    左右中
  4. 层序遍历
    按层遍历;

4.3. 搜索树

参考

  1. [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search
    Tree)及其衍生算法

5. 串 String

5.1. 概述

串是由零个或多个字符组成的有限序列,又称字符串

  1. 字符串查找 算法
    1. KMP算法及改进 //大话数据结构
    2. Sunny算法
    3. Boyer–Moore算法

5.2. 算法

5.2.1. 朴素模式匹配算法

普通遍历方法;蛮力算法;

5.2.2. KMP 算法

//字符串查找算法

  1. 优缺点
  2. 最坏情况下也是o(m+n)的,而遍历(普速模式匹配)是o(m*n);

参考

  1. KMP 算法
    //极客学院 包括:BM算法、Sunday算法;

5.2.3. Boyer–Moore算法

5.2.4. Sunday 算法


6. 图


7. 应用

7.1. 排序

  1. 数组排序
  2. 链表排序
  3. 表外排序

8. 区分 数据结构

8.1. 堆

概念区分

  1. 栈与堆

  2. 堆与二叉树

    1. 二叉树与堆
  3. 概念

    1. 堆是一种经过排序的树形数据结构,每个节点都有一个值。
    2. 通常我们所说的堆的数据结构,是指二叉堆
    3. 堆的特点是根节点的值最小(或最大),且根节点的两个子树也是一个堆。
  4. 区分

    1. 最大堆:父节点的键值总是大于或等于任何一个子节点的键值;
    2. 最小堆:父节点的键值总是小于或等于任何一个子节点的键值。 //均来自二叉堆
  5. 其他
    由于堆的这个特性,常用来实现优先队列堆的存取是随意的
    这就如同我们在图书馆的书架上取书,虽然书的摆放是有顺序的,
    但是我们想取任意一本时不必像栈一样,先取出前面所有的书,
    书架这种机制不同于箱子,我们可以直接取出我们想要的书。
    //堆排序;

参考:

  1. 二叉堆
    //百度百科
    二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。
    二叉堆有两种:最大堆最小堆
  2. 堆树(最大堆、最小堆)详解

8.2. 堆与二叉树的区别

  1. 区别
    最长见的数结构是搜索树,最常见的堆是大(小)根堆。差别就在于,堆的左右节点是没有大小关系的,而树一般是左中右(由大到小)。

  2. 树的分类
    20200813002819

参考:

  1. 二叉树与堆
    //可以看看
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值