数据结构(C)
来源:互联网 发布:网络机柜中u表示什么 编辑:程序博客网 时间:2024/05/21 06:54
整理自传智扫地僧教学视频
概念
程序 = 数据结构 + 算法
- 数据项 -> 数据元素 -> 数据对象
- 数据对象: 性质相同的数据元素的集合。
- 数据结构: 研究数据元素之间的关系。 (结点与结点之间的关系; 数组/链表/树/图)
- 数据的逻辑结构
- 集合
- 线性结构: 1对1
- 树形结构: 1对多
- 图状结构: 多对多
- 数据的物理结构(存储结构)
- 顺序存储
- 链式存储
- 索引
- 散列
- 数据的逻辑结构
- 算法: 特定问题求解步骤的描述。 指令的有限序列。
- 算法的度量
- 时间复杂度
- 空间复杂度
- 大O表示法: O(1) < O(logn) < O(n) < O(nlogn) < O(n2) < O(n3) < O(2n) < O(n!) < O(nn)
- 时间换空间、空间换时间
线性表
- 通用操作: 创建、销毁、获取长度、清空(回到初始化即刚创建的状态)、获取数据元素、插入数据元素、删除数据元素。
- 线性表顺序存储: 指针数组。提前确定好容量,存储每个数据元素的地址。
- 优点: 不需要为表中的逻辑关系增加额外的空间;可以快速获得合法位置的元素
- 缺点: 插入和删除需要移动大量的元素。
- 线性表链式存储 (单向链表)
链表算法和具体业务模型的分离 3个结构体:结点指针域、头结点、业务结点 - 循环链表
链表头新增数据项:游标
新增操作- 直接指定删除链表中的某个数据元素
CircleListNode *CircleList_DeleteNode(CircleList *list, CircleListNode *node); - 游标(slider)操作
- 重置游标,指向第一个元素
CircleListNode *CricleList_Reset(CircleList *list); - 获取游标指向的数据元素
CircleListNode *CircleList_Current(CircleList *list); - 返回当前指向的数据元素,然后移动指向下一个数据元素
CircleListNode *CircleList_Next(CircleList *list);
- 重置游标,指向第一个元素
- 直接指定删除链表中的某个数据元素
- 双向链表
数据元素中新增数据项: 指向前一数据元素的指针
新增操作: 游标前移 - 链表的操作逻辑和辅助指针变量
指针指向谁,就把谁的地址赋给指针;不断的给指针赋值,就是不断的改变指针的指向。
使用带有头部的链表,辅助指针变量指向头部,链表编号从零开始,辅助指针移动N次,指向第(N-1)个数据元素,第(N-1)个数据元素中保存了第N个数据元素的位置。使用带有头部,位置编号从0开始(头部不算)的单链表
栈
栈是一种特殊的线性表,只能在一端(栈顶)进行操作。
- 操作: 创建、销毁、清空、获取栈的大小、入栈、出栈、获取栈顶元素
模型(开口方向)的选择 - 栈的顺序存储: 用链表的顺序存储模拟。
- 栈的链式存储: 用单向链表模拟。 栈的业务结点转换为链表的业务结点
入栈的结点都是通过malloc()分配的,在出栈、清空栈、销毁栈时要通过free()释放内存 - 栈的应用
- 就近匹配
- 中缀、后缀表达式
- 中缀转后缀
从左到右遍历中缀表达式,若为数字直接输出;若为操作符: 比较与栈顶元素的优先级- 左括号’(’ 直接入栈,当遇到右括号’)’时,将栈中的操作符弹出并输出,直到遇到左括号’(‘。左括号’(‘只弹出不输出。除非处理右括号,否则绝不从栈中移走左括号
- 优先级高于栈顶的操作符,入栈。否则,弹出栈顶操作符输出直到优先级低于当前操作符,当前操作符入栈。
- 遍历表达式结束后,弹出栈中操作符到输出。
- 后缀表达式的计算
从左向右遍历表达式,遇到数字,入栈;遇到操作符时,弹出右操作数,弹出左操作数,计算出结果后入栈,直到遍历结束,栈中唯一的元素即运算结果。
- 中缀转后缀
队列
队列也是一种线性表,只允许在一端进行插入,在另一端进行删除。
- 操作: 创建、销毁、清除、入队、出队、获取队列的长度、获取队头元素
- 队列的顺序存储: 用链表的顺序存储模拟。
- 队列的链式存储: 用单链表模拟。
树 (链表+递归)
- 术语
- 根:没有前驱
- 叶子:没有后继
- 森林: 不相交的树的集合
- 有序树
- 无序树
- 结点的度:结点挂接的子树数,即直接后继的个数
- 树的度:所有结点度中的最大值 Max{各结点的度}
- 树的深度(高度)
- 后继结点: 该结点中序遍历的下一个结点。
- 前驱结点: 该结点中序遍历的上一个结点。
- 二叉树
- 性质
- 在第N层上最多有2N-1个结点
- 深度为K的二叉树,最多有2K-1个结点,至少有K个结点
- 任何一颗二叉树,若度为2的结点有n个,则叶子结点的个数为n+1。
- 完全二叉树: 共有K层,前K-1层与满二叉树一样,第K层结点靠左,中间不能有空。
- n个结点的完全二叉树,深度为 [log2n]+1
- 完全二叉树,从上到下,从左到右,从1开始编号,编号为i的结点,其左子编号为(2*i),右子编号为(2*i+1),父结点编号为(i/2), i=1为根,除外。顺序存储
- 非二叉树转换为二叉树 “左孩子右兄弟表示法”
- 将结点的所有兄弟结点连接起来。
- 对每个结点,只保留与左子结点的连接,与其他子结点的连接均删除。
- 性质
- 树的表示法 链式存储
- 二叉链表示
- 三叉链表法 (包含指向双亲的指针)
- 双亲链表表示 两张表(结点表、结点关系表);
- 二叉树的遍历
- 遍历顺序 D:根; L:左子树; R:右子树 规定先左后右,相对于根结点
- 先序遍历 DLR –前缀表达式
- 中序遍历 LDR –中缀表达式
- 后序遍历 LRD –后缀表达式
- 递归遍历
- 三种遍历的本质:访问路径相同,访问结点的时机不同。将printf()语句去掉,从递归的角度看,三种算法相同。每个结点都经过3次
- 第一次经过时访问 –> 先序遍历
- 第二次经过时访问 –> 中序遍历
- 第三次经过时访问 –> 后序遍历
- 三种遍历的本质:访问路径相同,访问结点的时机不同。将printf()语句去掉,从递归的角度看,三种算法相同。每个结点都经过3次
- 非递归遍历 二叉树的中序遍历 栈实现
- 步骤1:
- 如果结点有左子树,该结点入栈;否则,访问该结点
- 步骤二:
- 如果结点有右子树,重复步骤1;
- 如果结点没有右子树(结点访问完毕),根据栈顶元素回退(访问栈顶元素并出栈),再访问右子树,重复步骤1.
- 栈为空时,遍历结束。入栈的结点表示,本身没有被访问过,同时右子树也没有被访问过。
- 步骤1:
- 遍历顺序 D:根; L:左子树; R:右子树 规定先左后右,相对于根结点
树的创建和释放
- #号法: NULL位置设为#
- 根据遍历结果确定树
- 先序遍历和中序遍历可以确定一棵树;
- 后序遍历和中序遍历可以确定一棵树;
- 先序遍历和后序遍历不能确定一颗树。
- 树的释放
- 后序遍历释放
树的线索化
- 方法1: 结点增加两个域,标识lchild和rchild是否线索化。当lchild或rchild为NULL时,设置对应的线索化标识,lchild指向前驱,rchild指向后继
- 方法2: 通过链表。遍历访问结点时,将结点插入链表,遍历结束后,整个树线索化完成。
排序
- 排序的稳定性
- 排序算法
- 选择法: 依次取一个数,与剩余的未比较的数进行比较。2层循环。
- 插入排序: 依次取一个数,与之前的数比较,比它大向后移动。
- 冒泡法:相邻元素比较,符合条件交换。
- 冒泡法优化: 设置标记,若未发生交换,则已排好序,之后不用再进行比较。
- 希尔排序
- 快速排序
- 归并排序
阅读全文
0 0
- C++,数据结构
- 数据结构C
- 数据结构(C)
- 数据结构(C#)--单链表
- 数据结构(C#)--单链表
- 插入排序 --C数据结构
- 冒泡排序 C数据结构
- 基数排序 C语言数据结构
- 数据结构(C++)--二叉树
- 链式队列(数据结构C#)
- C数据结构 栈
- 2010c数据结构日志
- 数据结构---堆栈(C#)
- 数据结构---队列(C#)
- c 数据结构 单链表
- 二叉树(数据结构 c++)
- 数据结构(C#)-排序
- 数据结构---习题(C++)
- 排队论应用(M/M/1/∞)
- 一份简单的gulpfile 配置文件
- 从头到尾打印链表
- Android 数据库SQLite使用小结
- DOM解析和SAX解析的区别
- 数据结构(C)
- The Little Schemer 阅读笔记
- C++虚函数与纯虚函数用法与区别
- 程序猿—目标的重要性
- 脚本的生命周期函数和摄像机
- 大数据处理引擎Spark与Flink大比拼
- QT的学习(2)-构造函数的parent参数
- 公共基础知识之程序设计基础
- 算法: 有一堆纸币,自己和对方都只能选择纸币中最大的或纸币中最小的,用动态规划法求出怎样自己才能拿到最多的钱