├── .DS_Store ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md └── 数据结构 ├── .DS_Store ├── images ├── 001.CPU&&内存关系(32位).png ├── 101.数组的内存表示示意图.png ├── 102.链表内存示意图.png ├── 103.链表节点表示图.png ├── 104.双链表示意图.png ├── 105.链表创建过程.png ├── 106.链表节点插入.png ├── 107.链表节点删除.png ├── 200.栈堆引入.png ├── 201.栈示意图.png ├── 202.静态栈&动态栈.png ├── 203.括号检验.png ├── 300.队列示意图.png ├── 301.顺序队列示意图.png ├── 302.循环队列示意图.png ├── 303.循环队列.jpg ├── 400.函数调用走向.png ├── 401.func函数递归.png └── 402.hannuota.gif ├── 二叉树遍历.md ├── 常用算法整理.md ├── 数据结构(一)--入门和预备知识.md ├── 数据结构(三)--栈.md ├── 数据结构(二)--数组和链表.md ├── 数据结构(五)--递归.md ├── 数据结构(四)--队列.md └── 数据结构源码 ├── 01.结构体和指针 ├── CPointer.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── quxiaoyou.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── CPointer │ └── main.m ├── 02.数组 ├── 数组.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── quxiaoyou.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── 数组 │ └── main.m ├── 02.链表 ├── 链表.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── quxiaoyou.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── 链表 │ └── main.m ├── 03.栈 ├── 栈.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── quxiaoyou.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ └── xcschememanagement.plist └── 栈 │ ├── XYStack.h │ ├── XYStack.m │ └── main.m ├── 04.队列 ├── 队列.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcuserdata │ │ │ └── quxiaoyou.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ └── xcschemes │ │ └── xcschememanagement.plist └── 队列 │ └── main.m └── 05.递归 ├── 递归.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── quxiaoyou.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── quxiaoyou.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── 递归 └── main.m /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.m linguist-language=c 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 渠晓友 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 数据结构和算法 2 | 3 | 数据结构和算法笔记与快速入门 4 | 5 | 结合自己学习数据结构的笔记和相关代码,在这里整理并分享成文章。 6 | 7 | 主要供自己记录,日后回头翻看的时候也更加方便。 8 | 9 | 如果有缘人看到,并且能从中有收获那就最好了。 10 | 11 | 本仓库附有对应的文章内实现代码。 12 | 13 | 这里主要有如下章节: 14 | 15 | [数据结构(一)--入门和预备知识](./数据结构/数据结构(一)--入门和预备知识.md) 16 | 17 | [数据结构(二)--数组和链表](./数据结构/数据结构(二)--数组和链表.md) 18 | 19 | [数据结构(三)--栈](./数据结构/数据结构(三)--栈.md) 20 | 21 | [数据结构(四)--队列](./数据结构/数据结构(四)--队列.md) 22 | 23 | [数据结构(五)--递归](./数据结构/数据结构(五)--递归.md) 24 | 25 | [二叉树遍历](./数据结构/二叉树遍历.md) 26 | 27 | 持续更新··· 28 | 29 | -------------------------------------------------------------------------------- /数据结构/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/.DS_Store -------------------------------------------------------------------------------- /数据结构/images/001.CPU&&内存关系(32位).png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/001.CPU&&内存关系(32位).png -------------------------------------------------------------------------------- /数据结构/images/101.数组的内存表示示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/101.数组的内存表示示意图.png -------------------------------------------------------------------------------- /数据结构/images/102.链表内存示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/102.链表内存示意图.png -------------------------------------------------------------------------------- /数据结构/images/103.链表节点表示图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/103.链表节点表示图.png -------------------------------------------------------------------------------- /数据结构/images/104.双链表示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/104.双链表示意图.png -------------------------------------------------------------------------------- /数据结构/images/105.链表创建过程.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/105.链表创建过程.png -------------------------------------------------------------------------------- /数据结构/images/106.链表节点插入.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/106.链表节点插入.png -------------------------------------------------------------------------------- /数据结构/images/107.链表节点删除.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/107.链表节点删除.png -------------------------------------------------------------------------------- /数据结构/images/200.栈堆引入.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/200.栈堆引入.png -------------------------------------------------------------------------------- /数据结构/images/201.栈示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/201.栈示意图.png -------------------------------------------------------------------------------- /数据结构/images/202.静态栈&动态栈.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/202.静态栈&动态栈.png -------------------------------------------------------------------------------- /数据结构/images/203.括号检验.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/203.括号检验.png -------------------------------------------------------------------------------- /数据结构/images/300.队列示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/300.队列示意图.png -------------------------------------------------------------------------------- /数据结构/images/301.顺序队列示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/301.顺序队列示意图.png -------------------------------------------------------------------------------- /数据结构/images/302.循环队列示意图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/302.循环队列示意图.png -------------------------------------------------------------------------------- /数据结构/images/303.循环队列.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/303.循环队列.jpg -------------------------------------------------------------------------------- /数据结构/images/400.函数调用走向.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/400.函数调用走向.png -------------------------------------------------------------------------------- /数据结构/images/401.func函数递归.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/401.func函数递归.png -------------------------------------------------------------------------------- /数据结构/images/402.hannuota.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/images/402.hannuota.gif -------------------------------------------------------------------------------- /数据结构/二叉树遍历.md: -------------------------------------------------------------------------------- 1 | # 二叉树的遍历 2 | 3 | **二叉树遍历** 分为`前序遍历`、`中序遍历`和`后序遍历`。 4 | 5 | ## 前序遍历 (DLR) 6 | 7 | 先访问根节点,然后`前序遍历`左子树,然后`前序遍历`右子树。 FCADBEGHP (下图二叉树 a) 8 | 9 | ## 中序遍历 (LDR) 10 | 11 | `中序遍历`左子树,再访问根节点,然后再`中序遍历`右子树。 ACBDFEHGP (下图二叉树 a) 12 | 13 | ## 后序遍历 (LRD) 14 | 15 | `后序遍历`左子树,再`后续遍历`右子树,最后访问根节点。 ABDCHPGEF (下图二叉树 a) 16 | 17 | > 经验总结 18 | > `前`、`中`、`后` 代表的是 `根节点 的位置` 19 | > L 永远在 R 的左边, R 永远在 L 的右边,【左子树始终在左边,右子树始终在右边】 20 | 21 | ![二叉树a.png](https://upload-images.jianshu.io/upload_images/1256297-db2932e35509b7fa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 22 | 23 | 24 | 25 | ## 题型举例 & 分析 26 | 27 | #### 1.求下图中二叉树前序遍历的结果: 28 | 29 | ![1..png](https://upload-images.jianshu.io/upload_images/1256297-070e816fb37b4c6f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 30 | 31 | 32 | 根据前序遍历规则DLR可以得到答案:`ABDYECFXZ` 33 | 34 | #### 2. 某二叉树的前序遍历为 `ABCDEFG`,其中序遍历为 `DCBAEFG`,求该二叉树的后续遍历 35 | 36 | 此题需牢记概念: 37 | 前序遍历(DLR) ---> 可以得出 A 为根节点 38 | 中序遍历(LDR) ---> 可以得出 DCB 为左子树,EFG 为右子树 39 | 后序遍历(LRD) ---> 结合前中遍历,发现左子树 DCB 的前序遍历(DLR)和中序遍历(LDR)恰好相反。即可得出得出左子树 DCB 如果没有R,其前(DL)中(LD)遍历正好相反。即可得知左子树 DCB 为没有右子树。同样右子树 EFG 的前(DLR)中(LDR)遍历相同,即没有左子树正好符合。 40 | 41 | 可画出该二叉树为: 42 | ![2.png](https://upload-images.jianshu.io/upload_images/1256297-5c12e97bde4a8aaf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 43 | 44 | 45 | 46 | 其后续遍历为 DCBGFEA 47 | 48 | #### 3. 假设二叉树中序遍历 BCDA,前序遍历为 ABCD, 则后续遍历为 49 | 50 | 前序遍历 DLR 可以得出,根节点为 A,B为左子树或者右子树根节点。 51 | 从中序遍历 LDR 第一个为B,可以得出 B 是左子树的根节点。并且C是B的右子树,D是C的右子树 52 | 53 | 从分析中,可以得到该二叉树的图为 54 | ![3.png](https://upload-images.jianshu.io/upload_images/1256297-dc126839fa3aa5c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 55 | 56 | 57 | 后续遍历为 `DCBA` 58 | 59 | #### 4. 某二叉树的前序序列为 ABCD,中序序列为 DCBA, 求后序遍历: 60 | 61 | 前序 DLR ---> A 是根节点,B是左子树根节点,或者右子树根节点 62 | 中序 LDR ---> DCB 为其左子树 63 | 64 | 其中前序 BCD 和中序DCB 为相反,恰为 DL 和 LD。所以推测为没有右子树,图为第二题的左侧子树。 65 | 66 | > 规律 67 | > 此树没有右子树,看它三种姿势 68 | > 前序遍历 DLR --> DL 69 | > 中序遍历 LDR --> LD 70 | > 后续遍历 LRD --> LD 71 | > 可以发现:没有右子树,前中遍历相反,中后遍历相同 72 | 73 | #### 5. 某二叉树后序序列与中序序列均为 ABCDEFGH,求其前序序列 74 | 75 | 应用到第四题规律,其中序后序序列相同为:LD,说明没有右子树。且根节点为H 76 | 通过分析即为只有左子树的: H G F E D C B A 77 | 78 | #### 6. 在具有 n 个节点的二叉树中,如果各个节点的值各不相同,但前序遍历序列与中序遍历序列相同,则该二叉树的深度为(根节点在第一层):n 79 | 80 | 分析: 81 | 前序序列 DLR 82 | 中序序列 LDR 83 | 后续序列 LRD 84 | 其中前序和中序相同即 DR,没有左子树,即只有右节点的单叉树。即n层。 85 | 86 | **---end---** 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /数据结构/常用算法整理.md: -------------------------------------------------------------------------------- 1 | # 常用算法整理 2 | 3 | 此文件整理一下常用算法,经典算法,会在日常中持续更新... 4 | 5 | - 选择排序法 6 | 7 | 【基本思想】: 8 | ①对有 n 个数的序列,从中选出最小数,与第一个数交换位置 9 | ②除第一个数外,其余n-1个数再按①的方法选出次小的数,与第二个数交换 10 | ③重复①n-1次,最后得到递增序列 11 | 12 | - 冒泡排序法 13 | 14 | 【基本思想】: 15 | 相邻的数两两比较,将较小的调到前头。 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /数据结构/数据结构(一)--入门和预备知识.md: -------------------------------------------------------------------------------- 1 | # 数据结构(一)--入门和预备知识 2 | 3 | ## 1. 概述 4 | 5 | **数据结构定义:** 6 | 7 | 我们如何把现实中大量而复杂的问题以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(如元素的CURD、排序等)而执行的相应操作,这个相应的操作也叫算法。 8 | 9 | 数据结构 = 元素的存储 + 元素的关系的存储 10 | 算法 = 对数据存储的操作 11 | 12 | **算法:** 13 | 14 | 算法就是:解决问题的方法和步骤 15 | 16 | 衡量算法有如下标准: 17 | 18 | 1. 时间复杂度 19 |
程序要执行的次数,并非执行时间 20 | 2. 空间复杂度 21 |
算法执行过程中大概要占用的最大内存 22 | 3. 难易程度(可读性) 23 | 4. 健壮性 24 | 25 | ## 2. 数据结构的特点和地位 26 | 27 | **地位:** 28 | 29 | 数据结构处于软件中核心的地位。 30 | 31 | 如计算机内存中栈和堆的区别,不懂数据结构的人可能会认为内存就是分两大部分,一块叫栈,一块叫堆,显然这是非常肤浅且不正确的结论。 32 | 33 | 实际上如果一块内存是以压栈出栈的方式分配的内存,那么这块内存就叫栈内存,如果是以堆排序的方式分配的内存,那么这块内存就叫堆内存,其最根本的区别还是其内存分配算法的不同。 34 | 35 | 例如,函数的调用方式也是通过`压栈出栈`的方式来调用的,或者操作系统中多线程操作有`队列`的概念,`队列`用于保证多线程的操作顺序,这也是数据结构里面的内容、或者计算机编译原理里面有`语法树`的概念,这实际上就是数据结构里面的`树`,比如软件工程、数据库之类都有数据结构的影子。 36 | 37 | **特点:** 38 | 39 | 数据结构修炼的是内功,并不能直接立竿见影的可以解决现实问题,但是有了这门内功会在其他方面的学习中对你大有益处。 40 | 41 | ## 3. 预备知识(C语言) 42 | 43 | 学习数据结构应该具备如下知识: 44 | 45 | - 指针 46 | - 结构体 47 | - 动态内存的分配和释放 48 | - 跨函数使用内存 49 | 50 | 本小节主要介绍学习数据结构应该有的基础,并对相关知识稍作讲解。 51 | 52 | ### 指针 53 | 54 | 指针是 C语言 的灵魂,重要性不需多言。 55 | 56 | **指针定义** 57 | 58 | 地址: 59 |   地址是内存单元的编号 60 |   其编号是从 0 开始的非负整数 61 |   范围: 0 -- 0xFFFFFFFF (2^32 - 1) **注:此指x86平台,x64平台下最大内存地址为 (2^64 - 1)** 62 | 63 | 指针: 64 |   指针就是地址,地址就是指针。 65 |   指针变量是存放内存单元地址的变量,它内部保存的值是对应的地址,地址就是内存单元的编号(如内存地址值:0xffc0)。 66 |   指针的本质是一个操作受限的非负整数 67 |    68 | 在计算机系统中,CPU 可以直接操作内存,关于 CPU 对内存的操作与控制原理可以简单理解如下图 69 | ![001.CPU--内存关系(32位)](./images/001.CPU&&内存关系(32位).png) 70 | 71 | 地址线 : 确定操作哪个地址单元 72 | 控制线 : 控制该数据单元的读写属性 73 | 数据线 : 传输 CPU 和内存之间的数据 74 | 75 | **指针的分类** 76 | 77 | 1. 基本类型的指针 78 | 79 | ```objc 80 | int i = 10; // 定义一个 整形变量 i 初始值 10 81 | 82 | int *p = i; // 定义一个 整形的指针变量 p , 变量 p 指向 i 的地址 83 | 84 | int *p; // 这两行等价于上面一行 85 | p = &i; 86 | 87 | 1. p 存放了 i 的地址,我们就可以说“ p 指向了 i” ,但 p 和 i 是两个不同的变量,修改一方不会影响另一个的值。 88 | 2. *p 等价于 i ,i 等价于 *p;两者是一块内存空间,里面的值一变具变。 89 | ``` 90 | 91 | 2. 指针和函数 92 | 93 | ```objc 94 | // 修改外部实参的值 95 | void func(int * p) 96 | { 97 | *p = 100; // 函数内修改外部变量的值 98 | } 99 | 100 | // 修改外部实参的值,二级指针的值 101 | void func2(int ** p) 102 | { 103 | *p = 100; 104 | // 函数内修改外部变量的值 ,这里实际修改的是指针的内部的地址,这里直接自己修改并不严谨也不安全,只是为了表达意思 105 | } 106 | 107 | int main(void) 108 | { 109 | // 修改外部实参 110 | int i = 10; 111 | func(&i); 112 | printf("i = %d",i); 113 | 114 | // 修改外部二级指针 115 | int *p = i; // 等价于 int *p; p = &i; 116 | func(&p); 117 | printf("i = %d",i); 118 | 119 | return 0; 120 | } 121 | 122 | // 通过函数调用,改变函数外部变量(实参)的值 123 | 124 | ``` 125 | 3. 指针和数组 126 | 127 | 【指针】 和 【一维数组】 128 | 129 | ```objc 130 | int a[5] = {1,2,3,4,5 }; 131 | 132 | a[3] == *(a + 3) 133 | // 等价于 a[3] == *(3 + a) == 3[a]; 134 | // 3[a] 这种写法只是不常用,从原理上来说是正确的 a 等价于 a[0]; 135 | // a 是数组中第一个元素,每个元素占用内存单位长度相同, 136 | // a[i] 中的 i 实际代表的是单位长度的倍数 137 | ``` 138 | 139 | - 数组名:
140 |   一维数组名是个指针常量(它的值不可变)
141 |   它存放的是该一维数组的第一个元素的地址(一维数组名指向其第一个元素) 142 |    143 | - 下标和指针的关系: 144 |   (1)、 `a[i]` 等价于 `*(a + i)` 145 |   (2)、假设指针变量的名字为 p, 146 |   则 `p + i` 的值为 `p + i * (p 所指向的变量所占字节数)` 147 |   (3)、每个下标表示的是第 i+1 个元素,根据元素类型分配的字节长度不同(int 类型4个字节),每个字节都有对应的内存地址编号,指针变量 p 保存的是该元素首字节的地址。 148 | 149 | - 指针变量的运算:  150 |   指针变量不能相加、相乘、相除 151 |   如果两指针变量属于同一数组,则可以相减 152 |   指针变量可以加减一个整数,前提是最终结果不能超过指针最大可访问范围 153 |       154 | 155 | ```objc 156 | // 指针变量的运算 157 | p + i 的值是 p + i*(所指向的变量所占字节数) 158 | p - i 的值是 p - i*(所指向的变量所占字节数) 159 | p++ 等价于 p + 1 160 | p-- 等价于 p - 1 161 | 162 | 163 | // 下面是一个通过函数修改数组内部元素 164 | void my_Array(int *a , int length) 165 | { 166 | for(int i = 0; i < length; i++) 167 | { 168 | *a[i]++; // 给每个元素加 1 169 | } 170 | } 171 | 172 | int main(void){ 173 | 174 | int a[5] = {1,2,3,4,5}; 175 | my_Array(a , 5); // 调用 176 | } 177 | 178 | ``` 179 | 180 | ### 结构体 181 | 182 | **为什么会出现结构体**、 183 | 184 | 为了表示一些复杂的数据,而普通的基本数据无法满足要求. 185 | 186 | **什么叫结构体** 187 | 结构体是用户根据实际需要,自己定义的复合数据类型 188 | 189 | ```objc 190 | // 如学生类型 191 | struct Student{ 192 | int age; 193 | char * name; // name 不同,赋值方法不同 194 | char name2[100]; // 这个只能 strcpy(s.name2, "zhangwangdsd"); 字符串拷贝 195 | double height; 196 | }; 197 | ``` 198 | 199 | **如何使用结构体** 200 | 201 | 总结起来有两种结构体的使用方式:直接使用 && 通过指针使用 202 | struct Student ss = {12,"xiaoyou",1.73,"xiaozhang"}; 203 | struct Student *pst = &ss; 204 | 205 | ss.name ; 这里直接操作结构体本身 206 | pst -> name ; 这里通过指针地址操作,更加节省空间 207 | 208 | 209 | ```c 210 | struct Student{ // 自定义结构体 211 | int age; 212 | char * name; 213 | double height; 214 | char name2[100]; 215 | }; 216 | 217 | int main(void) { 218 | 219 | struct Student s = {12,"xiaoyou",1.73,"xiaozhang"}; 220 | 221 | // 直接使用 222 | printf(" age = %d \n name = %s \n height = %.2f \n",s.age,s.name,s.height); 223 | 224 | s.age = 21; 225 | s.name = "xiaozhu"; 226 | strcpy(s.name2, "zhangwangdsd"); // 字符串拷贝 227 | s.height = 1.70; 228 | 229 | printf(" age = %d \n name = %s \n height = %.2f \n %s \n",s.age,s.name,s.height,s.name2); 230 | 231 | // 以指针的方式使用 232 | struct Student *pst = &ss; 233 | pst -> name = "my new name"; 234 | 235 | printf(" name = %s\n",pst->name); 236 | printf(" name = %s\n",(*pst).name); 237 | 238 | // pst -> name 等价于 (*pst).name , 239 | // 而(*pst).name 又等价于 ss.name 240 | // 所以 pst -> name 等价于 ss.name 241 | 242 | return 0; 243 | } 244 | ``` 245 | 246 | **注意事项** 247 | 结构体变量的类型为: struct Student 248 | 结构体变量不能加减乘除,但是能够相互赋值 249 | 普通结构体变量和结构体指针变量作为函数传参的问题 250 | 251 | ```c 252 | typedef struct Student{ // 结构体定义 253 | int age; 254 | char * name; 255 | char name2[100]; 256 | double height; 257 | }myStudent; 258 | 259 | // 直接传递整个结构体数据,耗时 && 浪费内存空间 260 | void func(struct Student st); 261 | // 直接传递 只占用 4 byte 的指针,省时效率也高 <推荐用法> 262 | void func2(struct Student * pst); 263 | 264 | int main(void){ 265 | 266 | myStudent ss = {12,"xiaoyou",1.73}; 267 | func(ss); 268 | func2(&ss); 269 | return 0; 270 | } 271 | 272 | void func(struct Student st){ 273 | 274 | printf("age = %d \n name = %s",st.age,st.name); 275 | } 276 | 277 | void func2(struct Student * pst){ 278 | 279 | printf("age = %d \n name = %s",(*pst).age,(*pst).name); 280 | printf("age = %d \n name = %s",pst->age,pst->name); 281 | } 282 | 283 | ``` 284 | 285 | ### 动态内存分配和释放 286 | 287 | 平时直接创建数组的写法都是静态创建,创建完毕之后在整个程序的运行过程中,会固定占用对应的内存,不仅会造成内存空间浪费,还无法动态添加元素,所以局限性很大,而程序中我们为了避免这种情况,应该使用动态的方式创建和销毁数组。 288 | 289 | ```c 290 | // 静态创建数组 291 | int a[5] = {1,2,3,4,5}; 292 | ``` 293 | 294 | **动态构造一维数组** 295 | 296 | 动态构造一个 `int 型`的一维数组。 297 | 298 | ```c 299 | int *p = (int *)malloc(int length); 300 | 301 | 1. void * malloc(size_t __size) 函数,只有一个 int 类型的形参,表示要求系统分配的字节数 302 | 2. malloc 函数的功能是请求系统 length 个字节的内存空间,如果请求完成则返回的是第一个字节的地址, 303 | 如果请求不成功,则返回NULL 304 | 3. malloc 函数能且只能返回第一个字节的地址,所以我们需要把没有实际意义的第一个字节地址(干地址)转化为一个有实际意义的地址, 305 | 所以 malloc 前面必须加(数据类型 *),表示把这个无意义的地址转化为对应类型的地址 306 | 307 | 实例: 308 | int *p = (int *)malloc(50); 309 | 表示将系统分配的 50 个字节的第一个字节的地址转化为 int 类型的地址,准确的说是转化为 4 个一组的地址的首地址, 310 | 这样 p 就指向了第一个四个字节··· p+i 就指向了第 i+1 个四个字节,p[0],p[i]也就分别是第一个,第i+1个元素。 311 | 312 | double *p = (double *)malloc(80); 313 | 表示将系统分配的 80 个字节的第一个字节的地址转化为 double 类型的地址,准确的说是转化为 8 个一组的地址的首地址, 314 | 这样 p 就指向了第一个八个字节··· p+i 就指向了第 i+1 个八个字节,p[0],p[i]也就分别是第一个,第i+1个元素。 315 | 316 | 4. free(p); 317 | 释放 p 所指向的内存,而不是释放 p 本身所占用的内存 318 | 319 | ``` 320 | 代码示例如下: 321 | 322 | ```c 323 | void test2(void) 324 | { 325 | int len; 326 | printf("请输入你要动态创建的数组长度:"); 327 | scanf("%d",&len); 328 | 329 | int *pArr = (int *)malloc(len); // 动态创建数组 330 | *pArr = 4; // 相当于 a[0] = 4; 这里 pArr 就等于数组首地址,等于数组名 331 | pArr[2] = 5; // 相当于 a[2] = 5; 332 | 333 | printf("pArr[0] = %d \npArr[2] = %d\n",pArr[0],pArr[2]); 334 | 335 | free(pArr); // 使用完毕,释放对应的数组空间 336 | } 337 | ``` 338 | 339 | ### 跨函数使用内存 340 | 341 | 在函数内部分配的局部变量,在函数调用完成之后就会被系统回收,其内存也会消失。但是程序中常常需要定义一块内存,当我们用完之后再会回收。如 OC 语言中对象。所以需要保存住分配的内存,应该用动态分配内存,当用完之后再手动释放。这也是C语言的一个不足之处:内存需要我们手动创建和手动释放,这也是 OC 语言在开发 iOS 程序时候,我们所讲的MRC。【苹果也发现了这个不足,于 iOS 5 的时候推出了ARC 】 342 | 343 | 下面是一个跨函数使用内存的例子: 344 | 345 | ```c 346 | // 这个例子已经非常有面向对象的味道了 347 | 348 | typedef struct Student{ // 自定义 student 结构体 349 | int age; 350 | char * name; 351 | }myStudent; 352 | 353 | myStudent * createStudent(void); // 创建 student 354 | void showStudent(myStudent *); // 输出 student 355 | 356 | int main(void) { 357 | 358 | myStudent *p = createStudent(); // 创建 student 359 | showStudent(p); // 输出 student 360 | 361 | return 0; 362 | } 363 | 364 | myStudent * createStudent(void) 365 | { 366 | myStudent *p = (myStudent *)malloc(sizeof(myStudent)); 367 | p->age = 20; 368 | p->name = "xiaoyou"; 369 | return p; 370 | } 371 | 372 | void showStudent(myStudent *p) 373 | { 374 | printf("student.age = %d \nstudent.name = %s\n",p->age,p->name); 375 | } 376 | 377 | ``` 378 | 379 | ## 4. 小结 380 | 381 | 本文主要讲解了数据结构的定义和简介。 382 | 回顾了学习数据结构应该具备的一些 C语言 的基础知识,如指针、结构体、和内存等。 383 | 384 | 后面会继续开始对数据结构的讲解。 385 | 386 | 387 | -------------------------------------------------------------------------------- /数据结构/数据结构(三)--栈.md: -------------------------------------------------------------------------------- 1 | # 数据结构(三)--栈 2 | 3 | 通常程序开发中内存管理是非常重要的,而内存主要分为占内存和堆内存。那么栈和堆内存有什么区别呢?希望在这篇文章里能带你找到答案! 4 | 5 | ## 1. 栈和堆的引入 6 | 7 | 在一个简单的程序中我们定义和声明几个基本类型的变量、结构体和数组,先来直观看一下栈和堆的不同: 8 | 9 | ![200.栈堆引入.png](./images/200.栈堆引入.png) 10 | 11 | - 静态变量 和 局部变量是以压栈出栈的方式分配内存的,系统会在一个代码段中分配和回收局部变量,实际上每个代码段、函数都是一个或多个嵌套的栈,我们不需要手动管理栈区内存。 12 | - 动态内存是一种堆排序的方式分配内存的,内存分配好后便不会自动回收,需要程序员手动回收。否则就会造成内存泄漏,内存越用越少。 13 | 14 | 简单了解了一下程序中内存栈与堆的区别,下面就正式开始讲数据结构中的栈。 15 | (注意:数据结构栈、内存栈、函数调用栈三者在含义上略有不同,但是其核心思想和理念是相同的) 16 | 17 | ## 2. 栈的定义 18 | 19 | 栈是一种“先进后出”的一种数据结构,有压栈出栈两种操作方式。如下图: 20 | 21 | ![201.栈示意图.png](./images/201.栈示意图.png) 22 | 23 | 24 | ## 3. 栈的分类 25 | 26 | 栈主要分为两类: 27 | 28 | - 静态栈 29 | - 动态栈 30 | 31 | **【静态栈】** 32 | 33 | 静态栈的核心是数组,类似于一个连续内存的数组,我们只能操作其栈顶元素。 34 | 35 | 36 | **【动态栈】** 37 | 38 | 静态栈的核心是数组,类似于一个连续内存的数组,我们只能操作其栈顶节点。 39 | 40 | ![202.静态栈&动态栈.png](./images/202.静态栈&动态栈.png) 41 | 42 | 43 | 44 | 45 | ## 4. 栈的算法 46 | 47 | 栈的算法主要是压栈和出栈两种操作的算法,下面我就用代码来实现一个简单的栈。 48 | 49 | 首先要明白以下思路: 50 | 51 | - 栈操作的是一个一个节点 52 | - 栈本身也是一种存储的数据结构 53 | - 栈有`初始化`、`压栈`、`出栈`、`判空`、`遍历`、`清空`等主要方法 54 | 55 | 56 | 57 | ### 4.1 栈的头文件定义 58 | 59 | 头文件定义如下: 60 | 61 | ```c 62 | typedef struct Node{ // 节点 63 | 64 | int data; 65 | struct Node *pNext; 66 | 67 | }*PNODE,NODE; 68 | 69 | typedef struct Stack{ // 栈 70 | 71 | PNODE pTop; 72 | PNODE pBottom; 73 | 74 | }STACK,*PSTACK; 75 | 76 | /**栈的初始化*/ 77 | void init(PSTACK); 78 | /**压栈*/ 79 | void push(PSTACK,int); 80 | /**出栈*/ 81 | int pop(PSTACK , int *); 82 | /**遍历打印栈*/ 83 | void traverse(PSTACK); 84 | /**是否为空栈*/ 85 | int isEmpty(PSTACK); 86 | /**清空栈*/ 87 | void clearStack(PSTACK); 88 | ``` 89 | 90 | 有了头文件定义,基本就确定了栈的使用结构和使用方式。下面是在主函数中对这个栈的创建和使用。 91 | 92 | ```c 93 | int main(void){ 94 | 95 | STACK stack; // 声明一个栈 96 | init(&stack); // 初始化 97 | 98 | // 压栈 99 | push(&stack, 10); 100 | push(&stack, 20); 101 | push(&stack, 30); 102 | push(&stack, 40); 103 | push(&stack, 50); 104 | 105 | traverse(&stack); // 遍历打印栈 106 | 107 | int val; 108 | int isPopSuccess = pop(&stack,&val); 109 | if (isPopSuccess) { 110 | printf("pop 的值为 %d\n",val); 111 | } 112 | 113 | traverse(&stack); 114 | 115 | clearStack(&stack); // 清空栈 116 | traverse(&stack); 117 | 118 | return 0; 119 | } 120 | ``` 121 | 122 | ### 4.2 栈的初始化 123 | 124 | 思路: 125 | 拿到栈声明的指针,开辟一块内存空间给栈顶栈底,此时是一个空栈,栈顶栈底指向同一块内存,且栈底栈顶以外不再指向其他节点。 126 | 127 | ```c 128 | /**栈的初始化*/ 129 | void init(PSTACK pS){ 130 | 131 | pS->pTop = (PNODE)malloc(sizeof(NODE)); 132 | if (pS->pTop == NULL) { 133 | printf("内存分配失败退出"); 134 | return; 135 | }else 136 | { 137 | pS->pBottom = pS->pTop; 138 | pS->pTop->pNext = NULL; 139 | } 140 | } 141 | ``` 142 | 143 | ### 4.3 压栈 和 出栈 144 | 145 | 思路: 146 | 压栈是把新的节点放入栈顶,且每次压栈操作只能将新的节点放到栈的顶部。 147 | 出栈需判断是否原本为空栈,存在出栈失败的情况,把栈顶指向栈顶元素的下一个元素,并释放原来栈顶元素空间。 148 | 149 | ```c 150 | /** 151 | 压栈 152 | 153 | @param pS 执行压栈的栈指针 154 | @param val 被压栈的值 155 | */ 156 | void push(PSTACK pS,int val){ 157 | 158 | // 创建新节点,放到栈顶 159 | 160 | PNODE pNew = (PNODE)malloc(sizeof(NODE)); 161 | pNew->data = val; 162 | pNew->pNext = pS->pTop; 163 | 164 | pS->pTop = pNew; // 栈顶指针指向新元素 165 | } 166 | 167 | /** 168 | 出栈 169 | 170 | @param pS 执行出栈的栈地址 171 | @param val 出栈值的地址 172 | @return 是否出栈成功 173 | */ 174 | int pop(PSTACK pS , int *val){ 175 | 176 | if (isEmpty(pS)) { 177 | printf(" 空栈 ,出栈失败"); 178 | return 0; 179 | }else 180 | { 181 | PNODE p = pS->pTop; 182 | pS->pTop = p->pNext; 183 | 184 | if (val != NULL) { 185 | *val = p->data; 186 | } 187 | free(p); // 释放原来top内存 188 | p = NULL; 189 | return 1; 190 | } 191 | } 192 | 193 | /**是否为空栈*/ 194 | int isEmpty(PSTACK pS) 195 | { 196 | if (pS->pTop == pS->pBottom) { 197 | return 1; 198 | }else 199 | { 200 | return 0; 201 | } 202 | } 203 | ``` 204 | 205 | ### 4.4 栈的清空 和 遍历 206 | 207 | 当一个代码段执行完成之后,实际上就是这个栈所有分配的空间都被回收,栈随之被清空! 208 | 209 | 思路: 210 | 栈清空,实际就是需要循环执行出栈操作。 211 | 栈遍历,实际就是栈元素从栈顶一个个遍历到栈底,可以打印栈中元素的值 212 | 213 | ```c 214 | /**清空栈*/ 215 | void clearStack(PSTACK pS){ 216 | 217 | if (isEmpty(pS)) { 218 | return; 219 | }else{ 220 | PNODE p = pS->pTop; 221 | PNODE q = NULL; 222 | 223 | while (p!=pS->pBottom) { 224 | q = p->pNext; 225 | free(p); // 释放原栈顶元素空间 226 | p = q; 227 | } 228 | pS->pTop = pS->pBottom; 229 | } 230 | 231 | 232 | // 偷懒的做法 233 | // while (!isEmpty(pS)) { 234 | // pop(pS, NULL); 235 | // } 236 | } 237 | 238 | 239 | /**遍历打印栈*/ 240 | void traverse(PSTACK pS){ 241 | 242 | // 只要不是空栈,就一直输出 243 | PNODE p = pS->pTop; 244 | while (p != pS->pBottom) { 245 | 246 | printf("%d ",p->data); 247 | 248 | p = p->pNext; // 把top的下一个节点付给top,继续遍历 249 | } 250 | printf("\n"); 251 | } 252 | ``` 253 | 254 | 255 | 256 | ## 5. 栈的应用 257 | 258 | 栈结构固有的先进后出的特性,使它成为在程序设计中非常有用的工具,这里列举几个典型的例子。 259 | 260 | ### 5.1 数制转换 261 | 262 | 十进制数 N 和其他 d 进制数的转换是计算机实现计算的基本问题,其解决方法有很多种,其中一个简单的方法基于如下原理: 263 | `N = (N div d) * d + N mod d `(其中div是整除运算,mod 为求余运算) 264 | 例如:1348(10进制) == 2504(8进制)运算过程如下: 265 | 266 | N | N div 8 | N mod 8 267 | -----| ----|--------- 268 | 1348 | 168 | 4 269 | 168 | 21 | 0 270 | 21 | 2 | 5 271 | 2 | 0 | 2 272 | 273 | **需求:** 输入一个任意非负十进制整数,打印输出其对应的八进制整数 274 | 275 | **思路:** 由于上述计算过程是从低到高位顺序产生八进制数的各个数位,而打印输出,一般来说应从高位到低位进行,恰好和计算过程相反。因此可利用栈先进后出特性,将计算过程中得到的八进制数各位顺序进栈,再按出栈序列打印输出既为与输入对应的八进制数。 276 | 277 | ```c 278 | void conversion(void){ 279 | 280 | // 创建栈 281 | STACK S; 282 | init(&S); 283 | 284 | // 用户输入十进制数 285 | scanf("%d",&N); 286 | 287 | // 放入栈中 288 | while (N) { 289 | push(&S, N % 8); 290 | N = N / 8; 291 | } 292 | 293 | // 打印出来 294 | printf("对应八进制数字为:"); 295 | int a; 296 | while (!isEmpty(&S)) { 297 | pop(&S, &a); 298 | printf("%d",a); 299 | } 300 | printf("\n"); 301 | } 302 | 303 | ``` 304 | 305 | >**思考** 用数组实现貌似更简单,为什么不用数组? 306 | > 从算法上分析不难看出,栈的引入简化了程序设计的问题,划分了不同的关注层次,使思考范围缩小了。而使用数组不仅掩盖了问题的本质,还要分散精力去思路数组下标增减等细节问题。 307 | > 这也是早期面向对象编程的一种思想,要把对应的功能划分关注层次,在逻辑的实现上面更加专注问题的本质。 308 | 309 | ### 5.2 括号匹配的检验 310 | 311 | 编程语言中基本都允许使用 `(),[],{}`这几种括号,假设现在让使用两种,一段完整代码中其须成对匹配,检验括号是否匹配的方法可用"期待的紧迫程度"这个概念来描述。 312 | 313 | ![203.括号检验.png](./images/203.括号检验.png) 314 | 315 | 316 | 当计算机接受了第一个括号后,它期待着与其匹配的第八个括号出现,然而等来的确实第二个括号,此时第一个括号`[`只能暂时靠边,而迫切等待与第二个括号匹配的第七个括号`)`出现,类似地,等来的是第三个括号`[`,其期待的匹配程度比第二个更加急迫,则第二个括号也只能靠边,让位于第三个括号,显然第二个括号的期待急迫性高于第一个括号,在接受了第四个括号之后,第三个括号的期待得到满足,消解之后,第二个括号的期待匹配变成最紧迫的任务了·····,以此类推。 317 | 318 | 可见此处理过程与栈的特点相吻合,由此,在算法中设置一个栈,每读入一个括号,若是右括号则使至于栈顶的最紧迫的期待得以消解,若是不合法的情况(左括号),则作为一个新的更紧迫的期待压入栈中,自然使原来所有未消解的期待的紧迫性都降了一级。另外在算法开始和结束的时候,栈都应该是空的。 319 | 320 | 算法实现: 321 | 322 | ```c 323 | /** 324 | 检测括号(本实例用数字代替括号) 325 | 326 | [ ] --> 1 , 2 327 | ( ) --> 3 , 4 328 | 329 | */ 330 | void checkBracelet(void) 331 | { 332 | // 创建栈 333 | STACK S; 334 | init(&S); 335 | 336 | // 用户输入括号 337 | int N; 338 | printf("请输入对应的括号(end结束):\n"); 339 | scanf("%d",&N); 340 | 341 | if (isEmpty(&S)) { 342 | push(&S, N); 343 | printf("第一个括号输入\n"); 344 | traverse(&S); // 打印此时栈内容 345 | } 346 | 347 | while (!isEmpty(&S)) { 348 | 349 | // 用户输入括号 350 | int N; 351 | printf("请输入对应的括号(0结束):\n"); 352 | scanf("%d",&N); 353 | 354 | if (N == 0) { 355 | break; // 用户输入0直接退出 356 | } 357 | 358 | // 判断当前栈顶是否符合标准, 359 | if (S.pTop->data == N) { 360 | printf("消除一对\n"); 361 | pop(&S, NULL); 362 | traverse(&S); // 打印此时栈内容 363 | }else 364 | { 365 | printf("未消除\n"); 366 | push(&S, N); 367 | traverse(&S); // 打印此时栈内容 368 | } 369 | } 370 | } 371 | ``` 372 | 373 | 这里的实例我列举了两个,实际上还有很多。比如 **行编辑程序**、**迷宫求解**、**表达式求值**等。这里我就先不做列举了。 374 | 375 | ## 6. 小结 376 | 377 | 通过这里复习数据结构中栈的内容,感觉重新理解了很多计算机实现的底层知识,虽然不知道的更多,但是面对计算机心中又多了一层认知! 378 | 379 | 文中代码地址:[https://github.com/xiaoyouPrince/DataStructure](https://github.com/xiaoyouPrince/DataStructure) 380 | 381 | 382 | -------------------------------------------------------------------------------- /数据结构/数据结构(二)--数组和链表.md: -------------------------------------------------------------------------------- 1 | # 数据结构(二)--数组和链表 2 | 3 | 数据结构主要可以分为两大模块: 4 | 5 | - 线性结构 6 | - 非线性结构 7 | 8 | 本文主要开始讲线性结构。 9 | 10 | ## 什么是线性结构 11 | 12 | 线性结构,顾名思义,就是这些数据所有节点都能被一根线(指针)联系起来的一种结构。 13 | 14 | **线性结构的存储方式:** 15 | 16 | 1. 连续存储:【数组】 17 | 2. 离散存储:【链表】 18 | 19 | **线性结构的常见应用方式:** 20 | 21 | 1. 栈 22 | 2. 队列 23 | 24 | **专题 :【递归】** 25 | 26 | ## 数组和链表 27 | 28 | 本小节学习数组和链表,从底层去了解和实现数组与链表,并分析两者对应的优缺点 29 | 30 | ### 数组 31 | 32 | 数组是最常见的链式存储结构,它是一段连续的内存空间,在内存中我们可以简单表示为下图样式 33 | 34 | 35 | ![101.数组的内存表示示意图](./images/101.数组的内存表示示意图.png) 36 | 37 | 通过上图我们可以把代码中`int arr[6] = {1,2,3,4,5,6};`执行的操作从内存中脑补出来,同时我们可以简单分析一下,数组应该有的一些基本使用。如 38 | 39 | - 初始化、 40 | - 添加新元素、 41 | - 插入新元素、 42 | - 删除某个元素、 43 | - 判断是否为空数组、 44 | - 是否是满数组、 45 | - 排序 46 | - 倒序 47 | - 查询是否包含某个元素 48 | - ······ 49 | 50 | 本小节就带着你手把手实现一个简单的数组的封装,借此来了解数组的数据结构以及内部的一些基本算法知识。这里就简单的以一个 int 类型的数组来示例,后面学到泛型的时候便可更加好的理解数组的实现。 51 | 52 | 首先简单分析一下数组中基本的属性,我们有上面的数组内存中的逻辑图可以确定数组有对应的内存空间,有一个内存起始地址,因为系统分配内存的时候长度是一定的,所以数组中有一个表示最大长度的属性,数组中的元素也可能会根据实际个数不定,所以肯定有元素个数的标记,这个标记不仅可以拿来查看数组元素个数,也能确定了元素的下标。通过简单的分析我们可以总结数组中基本的属性如下: 53 | 54 | - 【pBase】 数组首字节地址 55 | - 【length】 数组长度(决定分配的内存大小) 56 | - 【count】 数组中有效元素个数 57 | 58 | 59 | 60 | 下面就根据上面的分析来实现一个简单的数组,这里只说一下思路,完整代码请在这里下载[数组实现代码](https://github.com/xiaoyouPrince/DataStructure) 61 | 62 | ```c 63 | // 定义个数组 64 | typedef struct Array { 65 | int length; // 数组长度 66 | int count; // 数组当前元素数 count 67 | int *pBase; // 数组的首字节地址 68 | }* PMyArray,MyArray; //两个别名,PMyArray 类似java中类名,定义的对象不带 * , MyArray类似于OC中的类型,定义的对象带 * 。 69 | 70 | // 要实现的一些基本方法 71 | 72 | /** 初始化数组*/ 73 | void init_Arr(MyArray *pArr, int len); 74 | /** 追加数组*/ 75 | bool append_Arr(MyArray *pArr, int value); 76 | /** 插入数组*/ 77 | bool insert_Arr(MyArray *pArr, int index , int value); 78 | /** 删除数组*/ 79 | bool delete_Arr(MyArray *pArr, int index , int * pVal); 80 | /** 是否满载*/ 81 | bool is_full(MyArray *pArr); 82 | /** 是否为空*/ 83 | bool is_empty(MyArray *pArr); 84 | /** 排序数组*/ 85 | void sort_Arr(MyArray *pArr); 86 | /** 展示数组*/ 87 | void show_Arr(MyArray *pArr); 88 | /** 倒序数组*/ 89 | void inversion_Arr(MyArray *pArr); 90 | 91 | /** 获取一个默认初始化的数组*/ 92 | MyArray * get_Arr(void); 93 | 94 | 95 | int main(void) { 96 | 97 | MyArray arr; // 声明 98 | int len = 6; // 定义数组长度 99 | init_Arr(&arr,len); // 初始化 100 | 101 | // 添加元素 102 | int time = 0; 103 | while (time < len) { 104 | append_Arr(&arr, 100 + time); 105 | time++; 106 | } 107 | 108 | insert_Arr(&arr, 6, 200); // 插入元素 109 | insert_Arr(&arr, 7, 300); 110 | insert_Arr(&arr, arr.count, 400); 111 | insert_Arr(&arr, 0, 500); 112 | insert_Arr(&arr, 3, 600); 113 | 114 | show_Arr(&arr); // 打印数组元素 115 | 116 | int val; 117 | //delete_Arr(&arr, 3 ,NULL); // 删除第三个元素 118 | delete_Arr(&arr, 3 ,&val); 119 | printf("被删除的元素是 %d \n",val); 120 | 121 | show_Arr(&arr); // 打印数组元素 122 | 123 | inversion_Arr(&arr); // 倒序排列一下 124 | 125 | show_Arr(&arr); // 打印数组元素 126 | 127 | sort_Arr(&arr); // 排序数组 128 | 129 | show_Arr(&arr); // 打印数组元素 130 | 131 | 132 | #pragma mark -- OOP 133 | 134 | // 类似于 OC 中的面向对象用法 135 | MyArray * array3 = get_Arr(); 136 | printf("array3 address is %p\n",array3); 137 | printf("array3 address is %p\n",&array3); 138 | show_Arr(array3); 139 | 140 | // 类似于 java 中的面向对象用法 141 | PMyArray myArray4 = get_Arr(); 142 | printf("array4 address is %p\n",myArray4); 143 | printf("array4 address is %p\n",&myArray4); 144 | show_Arr(myArray4); 145 | 146 | return 0; 147 | } 148 | 149 | // 初始化数组,对内部元素基本初始化 150 | void init_Arr(MyArray *pArr,int len){ 151 | 152 | (*pArr).pBase = (int *)malloc(sizeof(int) * len); // 先分配一段内存空间,长度为 len * int长度。 153 | if(pArr->pBase == NULL) 154 | { 155 | printf("内存分配失败,初始化失败\n"); 156 | exit(-1); // 终止程序 157 | }else 158 | { 159 | pArr->length = len; 160 | pArr->count = 0; 161 | } 162 | return; 163 | } 164 | 165 | /** 166 | 实现数组插入 167 | 168 | 1. 判断插入下标是否越界 169 | 2. 如果插入前数组已经满了,就增大一个长度,重新插入 170 | 3. 如果插入前数组未满 171 | 3.1 当插入位置小于最大元素下标,先把要插入目标点后面的元素往后移动一个单位。 如在{1,2,4,5}中第3个位置插入3,结果为{1,2,3,4,5} 172 | 3.2 当插入位置大于等于最大元素下标,直接在原来数组后面add最后一个元素。 如在{1,2}中第5个位置插入 3 结果为{1,2,3} 173 | 174 | @param pArr 要操作的数组的指针 175 | @param index 要插入的index 即下标 176 | @param value 要插入的值 177 | @return 返回插入成功/失败 178 | */ 179 | bool insert_Arr(MyArray *pArr, int index , int value){ 180 | // 为减少篇幅,建议直接下载源码 181 | } 182 | 183 | /** 184 | 实现数组删除某个元素 185 | 并可以从外部获得被删除元素的值 186 | 187 | 1. 判断删除下标是否越界 188 | 2. 判断原数组是否为空 189 | 3. 如果删除前先保存对应 index 的值赋值给外部变量 190 | 把要删除目标点后面的元素往前移动一个单位。 如在{1,2,3,4,5}中第3个位置删除3,结果为{1,2,4,5} 191 | 192 | @param pArr 要操作的数组的指针 193 | @param index 要伤处的index 即下标 194 | @param pVal 要删除值的地址 195 | @return 返回删除成功/失败 196 | */ 197 | bool delete_Arr(MyArray *pArr , int index ,int *pVal) 198 | { 199 | // 为减少篇幅,建议直接下载源码 200 | } 201 | 202 | /** 203 | 往数组尾部添加元素 204 | 205 | @param pArr 数组指针 206 | @param value 要添加的元素值 207 | @return 添加成功/失败 208 | */ 209 | bool append_Arr(MyArray *pArr,int value){ 210 | 211 | if (!is_full(pArr)) { // 判断是不是已经满了数组 212 | // 数组未满,添加 213 | pArr->pBase[pArr->count] = value; 214 | pArr->count++; 215 | return true; 216 | 217 | }else{ 218 | printf("数组已经满了,无法从尾部追加元素,请尝试从前面插入\n"); 219 | return false; 220 | } 221 | 222 | } 223 | 224 | // 为了控制篇幅,这里不再进行罗列,可以直接去下载源码对比查看 225 | 226 | ``` 227 | 228 | 229 | 230 | 数组的内存结构是线性的,通过这个例子的实现也更加容易理解。数组是一种常用的也是固定内存排序线性结构。然而在很多情况下是数据在内存中并不会这样线性的去排布。 231 | > 虽说C语言是面向过程的语言,事实上这只是一种表象,学了数据结构其实我们可以发现我们完全可以用 C语言 实现面向对象语言的特性。事实上几乎所有的操作系统内核、机器语言底层、编译器层面都是使用 C语言 来实现的。 232 | 233 | 234 | 235 | ### 链表 236 | 237 | 链表是一种元素内存空间离散排列的线性数据结构。它的内存存储示意图大致如下: 238 | 239 | 240 | ![102.链表内存示意图](./images/102.链表内存示意图.png) 241 | 242 | 243 | 链表是整个数据结构的一个基础,后面的线性结构几乎都需用到链表的知识,下面就从这几个方面来介绍链表。 244 | 245 | - 定义 246 | - 分类 247 | - 算法 248 | - 优缺点 249 | 250 | **【链表定义/特点】** 251 | n个节点离散分配 252 | 彼此通过指针相连 253 | 每个节点只有一个前驱节点,每个节点只有一个后续节点 254 | 首节点没有前驱节点,尾节点没有后续节点 255 | 256 | **首节点:** 257 | 第一个有效节点 258 | 259 | **尾节点:** 260 | 最后一个有效节点 261 | 262 | **头结点:** 263 | 第一个有效节点前面的那个节点,头结点并不存放有效数据,加头结点的目的主要是为了方便对链表的操作,头结点的数据类型和首节点一样 264 | 265 | **头指针:** 266 | 指向头结点的指针变量 267 | 268 | **尾指针:** 269 | 指向尾节点的指针变量 270 | 271 | 272 | **确定一个链表需要的最少的参数有哪些?** 273 | 根据链表的示意图可以简单推出来所有该链表的信息。 274 | 实际上只需要一个关键信息:**头指针** 275 | 因为我们通过头指针就可以推算出链表的其他所有信息。 276 | 277 | **【节点的表示】** 278 | 279 | ![103.链表节点表示图](./images/103.链表节点表示图.png) 280 | 281 | 282 | 283 | 284 | ```c 285 | // 代码的表示如下 286 | typedef struct Node{ 287 | int data; //数据域 288 | struct Node *pNext; // 指针域 - 指向相同类型的下一个节点 289 | }*PNODE,NODE; // PNODE 等价于 struct Node * , NODE 等价于 struct Node 290 | 291 | 【只需要拿到 pNext 指针就能推算出整个链表】 292 | ``` 293 | 294 | **【链表的分类】** 295 | 链表可以分为如下类别: 296 | 297 | - 单链表 -- 上面的实例 298 | - 双链表 -- 每个节点有两个指针域,分别指向前后两个节点
299 | ![104.双链表示意图](./images/104.双链表示意图.png) 300 | 301 | 302 | - 循环链表 -- 能通过任何一个节点找到其他所有节点的链表,环形链表 303 | - 非循环链表 -- 非环形普通列表 304 | 305 | **【关于链表的常见算法】** 306 | 307 | 常见算法有: 308 | 309 | - 创建链表 310 | - 遍历 311 | - 查找 312 | - 清空 313 | - 销毁 314 | - 求长度 315 | - 排序 316 | - 删除节点 317 | - 插入节点 318 | - ····· 319 | 320 | 下面就逐步讲一下各个算法的思路,用为算法的方式来帮助理解 321 | 322 | **1 创建链表** 323 | 324 | 创建链表,首先需要确定链表的长度 int length 然后根据长度创建对应个数的节点,并把新创建的节点挂到链表的最后。简单来说就是: 325 | 326 | 1 创建头结点 327 | 2 循环创建新节点挂到链表尾部 328 | 329 | 创建头节点,首先要创建一个没有存储值的头节点,我们本身定义了 NODE 结构体,可以根据NODE类型动态分配一块内存空间 330 | 331 | ```c 332 | // 创建一个值域为空的头结点,给头指针分配内存 333 | PNODE pHead = (PNODE)malloc(sizeof(PNODE)); // 头指针 334 | ``` 335 | 336 | 创建新节点,需要根据定义的长度循环,这里的难点就是如何把新节点挂到链表尾部【这里还是要明确指针和指针变量的概念,这样会更好理解一些】 337 | 为了能让新创建的节点挂到尾部,我们直接使用pHead->pNext = pNew; 338 | 是不行的,这样只能最后添加一个,并且其他的都会被泄漏。这里我们使用一个站位尾节点来表示尾节点 339 | 340 | ``` 341 | PNODE pTail = pHead; // 站位尾节点,直接赋值给 pTail,这是栈内存分配; 342 | pTail->pNext = NULL; 343 | 344 | for循环{ 345 | // 1.保存值和指针,变成完整新节点 346 | pNew->data = val; 347 | pNew->pNext = NULL; 348 | // 2.当前新节点追加到原来尾节点后面 349 | pTail->pNext = pNew; 350 | // 3.新节点变成原来尾节点 351 | pTail = pNew; 352 | } 353 | ``` 354 | 为了便于理解,请先弄清楚,指针和指针变量区别,下图逐步讲解 355 | ![105.链表创建过程](./images/105.链表创建过程.png) 356 | 357 | 358 | **2 遍历链表** 359 | 360 | 遍历链表思路: 361 | 遍历链表只能通过头结点的 pNext 指针找到下一个节点,并循环到 pNext == NULL 为止,分别打印 值域的值即可。 362 | 363 | ```c 364 | // 通过头节点遍历后面节点 365 | PNODE p = pHead->pNext; //获得首节点 366 | while (p != NULL) { 367 | printf("data = %d \n",p->data); 368 | p = p->pNext; 369 | } 370 | 371 | printf("遍历完毕,退出\n"); 372 | return; 373 | ``` 374 | 375 | **3 判断是否为空链表** 376 | 377 | 判断是够为空链表,直接拿头结点的 pNext 指针取值判断是否为 NULL 即可 378 | 379 | ```c 380 | bool isEmpty_list(PNODE pHead) 381 | { 382 | if ((*pHead).pNext == NULL) { 383 | return false; 384 | }else{ 385 | return true; 386 | } 387 | } 388 | ``` 389 | 390 | **4 求链表长度** 391 | 392 | 求链表长度类似于遍历链表,这里主要是计算有效节点的个数,这个个数就是长度 393 | 394 | ```c 395 | int length_list(PNODE pHead) 396 | { 397 | PNODE p = pHead->pNext; 398 | int len = 0; 399 | while (p->pNext == NULL) { 400 | len++; 401 | p = p->pNext; 402 | } 403 | return len; 404 | } 405 | ``` 406 | 407 | 408 | 409 | **5 插入节点** 410 | 411 | ![106.链表节点插入](./images/106.链表节点插入.png) 412 | 413 | ```c 414 | 其实思路很简单,主要是吧 p指向节点的的pNext 指向 q, 415 | 然后q所指向的下个节点直接指向原来p所指向的节点。 416 | 伪代码如下: 417 | 418 | temp = p->pNext; 419 | p->pNext -> q; 420 | q->pNext = temp; 421 | 422 | 或者直接 423 | q->pNext = P->pNext; 424 | P->pNext = q; 425 | ``` 426 | 427 | 本方法代码实现 428 | 429 | ```c 430 | bool insert_list(PNODE pHead , int pos , int val){ 431 | 432 | // 判断位置是否合法 433 | PNODE q = pHead; // 要插入的位置,如果是 <= 0,则直接插到最前面,如果是 pos = 1 就插入第一个后面,pos = n,就插到第 n 个后面 434 | int i = 0; 435 | while (i < pos) { 436 | if (q->pNext == NULL) { 437 | printf("要插入的位置不合法;大于链表长度\n"); 438 | break; 439 | }else{ 440 | q = q->pNext; //要被插入的节点 441 | i++; 442 | } 443 | } 444 | 445 | // 插入操作 446 | PNODE p = (PNODE)malloc(sizeof(NODE)); 447 | if (p == NULL) { 448 | printf("动态分配内存失败\n"); 449 | exit(0); 450 | } 451 | p->data = val; 452 | 453 | // 前一个节点为q, 直接添加到 q 后面。 454 | p->pNext = q->pNext; 455 | q->pNext = p; 456 | 457 | return true; 458 | } 459 | ``` 460 | **6 删除节点** 461 | 462 | ![107.链表节点删除](./images/107.链表节点删除.png) 463 | 464 | ```c 465 | // 思路: 466 | // 想要删除后面的节点,直接让 p 的指针域指向下下个节点就完成了 467 | // 这里的删除其实很方便,但是有个容易造成内存泄漏的误区 468 | // 因为直接删除之后,我们就无法在拿到 p 后面的节点的地址,然后无法释放,最终内存泄漏 469 | 470 | // 最终实现: 471 | temp = p->pNext; // 临时变量保存要删除节点地址 472 | p->pNext = p->pNext-pNext; // p 的指针域指向下下个节点 473 | free(temp); // 释放被删除节点内存 474 | ``` 475 | 476 | 代码实现 477 | 478 | ```c 479 | bool delete_list(PNODE pHead , int pos , int * val){ 480 | 481 | // 找到要被删除的元素保存起来 482 | PNODE p = pHead; 483 | int i = 0; 484 | while (i < pos - 1) { // 找到被删除节点的前一个节点 485 | 486 | if (p->pNext == NULL) { 487 | break; 488 | } 489 | p = p->pNext; 490 | i++; 491 | } 492 | 493 | if (i < pos && p->pNext == NULL) { 494 | printf("你要删除的位置非法,此位置不在链表长度范围之内\n"); 495 | return false; 496 | } 497 | 498 | // 找到了要被删除的那个节点 499 | PNODE t = p->pNext;; 500 | *val = t->data; // 把被删除节点的值传给外面 501 | 502 | p->pNext = t->pNext; // 直接指向后面一个节点 503 | free(t); // 释放被删除节点内存,防止内存泄漏 504 | 505 | return true; 506 | } 507 | ``` 508 | 509 | **7 链表排序** 510 | 511 | 链表排序同数组不同,但很相似,都是把所有元素遍历然后找到相邻或者相反的值互换位置。 512 | 513 | 参考数组排序我们可以看一下代码实现 514 | 515 | ``` 516 | void sort_list(PNODE pHead) 517 | { 518 | 519 | // 数组的排序算法 <-> 链表排序互相对比更好学习排序 520 | // for (i = 0 ; i < len - 1; i++) { // 外围的排序次数 ,没执行完以此只能确定某一最大或最小值 521 | // for (j = i + 1; j < len; j++) { // 内循环的排序次数 ,执行完一次把 n 个元素,对比 n-1 次并换位置 522 | // 523 | // if ( a[i] < a[j]) { 524 | // t = a[i]; 525 | // a[i] = a[j]; 526 | // a[j] = t; 527 | // } 528 | // } 529 | // } 530 | 531 | // 排序的算法有很多种 532 | int len = length_list(pHead); 533 | int i , j , t; 534 | PNODE p , q; 535 | 536 | for (i = 0 , p = pHead->pNext; i < len - 1; i++ , p = p->pNext) { // 外围的排序次数 ,没执行完以此只能确定某一最大或最小值 537 | for (j = i + 1 , q = p->pNext; j < len; j++ , q = q->pNext) { // 内循环的排序次数 ,执行完一次把 n 个元素,对比 n-1 次并换位置 538 | 539 | if (p->data > q->data) { // 比较两个节点数值,并换位置 540 | t = p->data; 541 | p->data = q->data; 542 | q->data = t; 543 | } 544 | } 545 | } 546 | 547 | return; 548 | } 549 | ``` 550 | 551 | ## 小结和感悟 552 | 553 | 数组和链表内部是不一样的,但是他们的排序的思路确实一样的,比如冒泡。 554 | 从排序的思路上都是前一个跟后一个元素比较,把小的放到前面,以此类推 555 | 556 | **算法:**
557 | **狭义的算法:** 与数据的存储方式密切相关
558 | **广义的算法:** 与数据的存储方式无关
559 | **泛型:** 利用某种技术达到同一种效果:不同的存储方式,执行的方式是一样的 560 | 561 | 如何学习算法? 562 | 563 | - 看真题流程 564 | - 分析每个语句的功能 565 | - 试数 566 | 567 | 自己搞不定,就去看答案,把答案弄懂,实在不行就先记住答案。 568 | 569 | 570 | 本文从数据结构的线性结构开始,分析了两种线性结构【数组】和【链表】, 571 | 进而逐步讲解和自己手动实现了数组和链表。 572 | 573 | 通过这两个结构,在讲解过程中也代入了一写算法的基础知识,希望能对大家有所帮助! 574 | 575 | 本文中所有代码连接地址如下:[https://github.com/xiaoyouPrince/DataStructure](https://github.com/xiaoyouPrince/DataStructure); 576 | 577 | -------------------------------------------------------------------------------- /数据结构/数据结构(五)--递归.md: -------------------------------------------------------------------------------- 1 | 2 | # 数据结构(五)--递归 3 | 4 | **首先思考一个问题,当A函数调用B函数,A函数是如何调用B函数的?** 5 | 6 | 在一个函数调用期间,调用另一个函数时,在执行被调用函数之前,系统需要先完成三件事 7 | 8 | 1. 将所有的实在参数返回的地址等信息传递给被调用函数保存 9 | 2. 给被调函数的局部变量分配存储区 10 | 3. 将控制权限转移到被调函数的入口 11 | 12 | 而从被调函数返回到调用函数之前,系统也会完成三件工作 13 | 14 | 1. 保存被调函数计算结果 15 | 2. 释放被调函数数据区 16 | 3. 依照被调函数保存的返回值地址,将控制权限转移给调用函数 17 | 18 | 当有多个函数构成嵌套调用时,按照`后调用先返回`,函数之间的传递和控制转移,必须借助栈来实现。即系统将整个程序运行所需的数据空间放在一个栈中,每当调用一个函数时,就为它在栈顶分配一个存储区,每当从一个函数退出时就释放它的存储区,则当前正运行的函数数据区必须在栈顶。 19 | 20 | **以上便是函数调用过程,也是本文学习递归知识的基础** 21 | 22 | ## 1. 递归的定义 23 | 24 | **递归**指一个函数直接或者间接调用自己 25 | 26 | **使用递归需要满足的三个条件:** 27 | 28 | - 递归必须有一个明确的终止条件 29 | - 该函数所处理的数据规模递减 30 | - 这个转化必须是可解的 31 | 32 | ## 2. 不同函数之间的相互调用 33 | 34 | 了解了函数之间相互调用规则之后,来看一下不同函数之间相互调用的例子 35 | 36 | 假定有三个函数 a,b,c 之间相互调用. 37 | 38 | ```c 39 | void a(){ 40 | printf("aaaa\n"); 41 | b(); 42 | printf("1111\n"); 43 | } 44 | 45 | void b(){ 46 | printf("bbbb\n"); 47 | c(); 48 | printf("2222\n"); 49 | } 50 | 51 | void c(){ 52 | printf("cccc\n"); 53 | // a(); // 想想这里调用a会出现什么情况? 54 | printf("3333\n"); 55 | } 56 | 57 | int main() { 58 | a(); 59 | return EXIT_SUCCESS; 60 | } 61 | ``` 62 | 63 | 打印结果如下 64 | 65 | ```c 66 | aaaa 67 | bbbb 68 | cccc 69 | 3333 70 | 2222 71 | 1111 72 | ``` 73 | 74 | 由此结合函数间调用的流程可清楚看到函数执行过程中的走向如图 75 | 76 | ![400.函数调用走向](./images/400.函数调用走向.png) 77 | 78 | 此时再想代码中注释的那行 `a()` 调用,很容易就能想清楚整体走向:即函数一直 a,b,c,a,b,c ... 循环调用,而没有返回,最终导致函数调用栈溢出,从而进程被系统杀死。这实际上造成了一个循环递归,类似于死循环 79 | 80 | ## 3.函数递归调用,自己调用自己 81 | 82 | 假定有一个函数 func() 83 | 84 | ```c 85 | void func(int num){ 86 | if (num == 1){ 87 | printf("执行目标代码\n"); 88 | } 89 | else 90 | { 91 | printf("递归自己\n"); 92 | func(num - 1); 93 | } 94 | } 95 | 96 | int main() { 97 | func(3); 98 | return EXIT_SUCCESS; 99 | } 100 | ``` 101 | 102 | 打印结果如下 103 | 104 | ```c 105 | 递归自己 106 | 递归自己 107 | 执行真实代码 108 | ``` 109 | 110 | 集合函数调用流程可以得到如下函数调用路径 111 | ![401.func函数递归](./images/401.func函数递归.png) 112 | 113 | ## 递归实例 114 | 115 | 本小节列举了以下几种情况的递归实例 116 | 117 | - 求阶乘 118 | - 求和 119 | - 汉诺塔问题 120 | 121 | ### 实例1,求数字 n 的阶乘 122 | 123 | **阶乘**即一个数从 n * (n-1) * (n-2) * ... * 1;用数学表示为 **n!** 124 | 125 | 求阶乘可以根据定义用循环法、也可以用递归法。下面分别用两种方法来求解阶乘 126 | 127 | **普通的循环法求阶乘** 128 | 129 | ```c 130 | int getFactorial(int num){ 131 | 132 | // 0 验证入参为大于0的整数 133 | if (num<1) { 134 | return 0; 135 | } 136 | 137 | 138 | int result = num; 139 | 140 | // 1. for 循环求解 141 | for( int i = num-1; i >= 1; i--){ 142 | result = i * result; 143 | } 144 | return result; 145 | } 146 | ``` 147 | 148 | 使用递归方式 149 | 150 | ```c 151 | int getFactorial(int num){ 152 | 153 | 154 | // 0 验证入参为大于0的整数 155 | if (num<1) { 156 | return 0; 157 | } 158 | 159 | int result = num; 160 | // 2. 递归求解 161 | if (num == 1) { 162 | return 1; 163 | }else 164 | { 165 | return result * getFactorial(num-1); 166 | } 167 | return result; 168 | } 169 | ``` 170 | 由于 int 类型限制,求到的结果最大为 32bit。即-2^31~2^31-1范围大小,因此它们能表示的整数范围为-2147483648~2147483647,所以上面函数能求到的最大阶乘数字为11.如果入参超过11即int值表达的数字内存溢出。实际使用应该根据需求使用更大的类型值。 171 | 172 | ### 实例2 求数字 1+2+3+ ... +n 的累加之和 173 | 174 | 此问题也可用两种方法来分别求解。 175 | 176 | **for循环求累加** 177 | 178 | ```c 179 | /// 求一个数字的累加和 180 | unsigned long getSum(int num){ 181 | 182 | // 0 验证入参为大于0的整数 183 | if (num<1) { 184 | return 0; 185 | } 186 | 187 | unsigned long result = num; 188 | // 1. for 循环求解 189 | for( int i = num-1; i >= 1; i--){ 190 | result = i + result; 191 | } 192 | return result; 193 | } 194 | ``` 195 | 196 | **递归求累加之和** 197 | 198 | ```c 199 | /// 求一个数字的累加和 200 | unsigned long getSum(int num){ 201 | 202 | // 0 验证入参为大于0的整数 203 | if (num<1) { 204 | return 0; 205 | } 206 | 207 | unsigned long result = num; 208 | // 2. 递归求解 209 | if (num == 1) { 210 | return 1; 211 | }else 212 | { 213 | return result + getSum(num-1); 214 | } 215 | return result; 216 | } 217 | ``` 218 | 219 | ### 汉诺塔问题 220 | 221 | 汉诺塔是源自印度神话里面的玩具。 222 | 传上帝创造世界的时候做了三根金刚石柱子,在一个柱子上从上往下按照大小顺序摞着 64 片黄金圆盘 223 | 上帝命令婆罗门把圆盘从下面开始按照大小顺序重新摆放到另一根柱子上。并且规定,在小圆盘的上面不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。 224 | 225 | 如图可以示意一个三层汉诺塔问题: 226 | ![402.hannuota](./images/402.hannuota.gif) 227 | 228 | 根据示意图结合递归思路。可以总结归纳出如下伪算法 229 | 230 | ```c 231 | if(n == 1){ 232 | 直接将该盘子移动到 C 柱子上 233 | } 234 | 235 | if(n > 1){ 236 | 1. 先将 A 柱子上的前 n-1 个盘子从 A 借助 C 移到 B 237 | 2. 将 A 柱子上的第 n 个盘子直接移动到 C 238 | 3. 再将 B 柱子上的 n-1 个盘子借助 A 移动到 C 239 | } 240 | ``` 241 | 242 | 此处可以发现问题难度一下提升了很多,这样的问题再用循环似乎就无从下手了。只能从递归的角度思考,并且问题操作步骤过于复杂,我们只能分析出来每层步骤之间的关系来使用递归来处理问题。有兴趣的话好好思考并感受一下递归的优势。 243 | 244 | 源码请见代码文件 245 | 246 | 247 | ## 递归和循环的关系 248 | 249 | 从上面的例子中可以发现,同一个问题既可以用循环实现也可以使用递归实现,它们之间由于实现方式不同,其各自的优缺点也是显而易见的。 250 | 251 | **递归:** 252 | 253 | - 易于理解 254 | - 速度慢(函数调用需要开辟更多内存空间,传递各种参数) 255 | - 需要存储空间大 256 | 257 | **循环** 258 | 259 | - 不易理解 260 | - 速度快(不会新开辟空间,也没有额外参数传递) 261 | - 占用存储空间小 262 | 263 | **虽然递归有一些显著的缺点,但是在解决一些树、图等复杂数据结构问题的时候,只能用递归来处理** 264 | 265 | ### 递归的应用 266 | 267 | 数据结构后面会讲到树、森林、图等数据结构,这些非线性的复杂的数据结构的很多算法都是使用递归来实现的。 268 | 269 | 很多数学公式就是以递归的方式来定义的: 270 | 271 | 如斐波拉切序列: 1 2 3 5 8 13 21 34 ... **后面一个数是前两项之和** 272 | 273 | ## 小结 274 | 275 | 递归在很多小问题面前,几乎没有优势,建议用循环方式处理。但是需要理解递归的思路,**只理解递归两层之间的交接,以及递归终结的条件**。当遇到一些复杂问题的时候才是递归真正发挥作用的时候。 276 | 277 | 本小节是后续数据结构**树**和**图**的基础,欢迎持续关注... 278 | 279 | -------------------------------------------------------------------------------- /数据结构/数据结构(四)--队列.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 数据结构(四)--队列 4 | 5 | 本文主要讲解了队列的定义和队列主要功能实现的算法。最后会列举一些队列在程序设计当中常见的应用实例!相信了解了队列对你理解数据结构和程序设计会更加有益处! 6 | 7 | ## 1. 队列的定义 8 | 9 | **队列 (Queue)**是一种先进先出(first in first out : **FIFO**)的线性表。它只允许在表的一端进行插入,在另一端进行删除元素。这和我们平时战队买票很一样。最早进入队列的元素最先离开,在队列中,允许插入的一端叫做**队尾(rear)**,允许删除的一段则称为**队头(front)**.示意图如下: 10 | ![300.队列示意图](./images/300.队列示意图.png) 11 | 12 | 13 | ## 2. 队列的分类 14 | 15 | 队列主要分为两类: 16 | 17 | - 链式队列:链式队列即用链表实现的队列 18 | - 顺序队列:顺序队列是用数组实现的队列,顺序队列通常必须是循环队列 19 | 20 | 本文主要以顺序队列(循环队列)为例,通过如下几个问题来分析和介绍顺序队列的相关知识,(链式队列内部以链表实现相对更加简单) 21 | 22 | 1. 顺序队列为什么是循环队列? 23 | 2. 一共需要几个参数,分别是什么含义? 24 | 3. 入队伪算法思路 25 | 4. 出队伪算法思路 26 | 5. 如何判断循环队列是否为空 27 | 6. 如何判断循环队列已满 28 | 7. 什么时候该使用顺序队列?什么时候该使用链式队列 29 | 30 | ### 2.0 循环队列--队列的顺序表示和实现整体分析 31 | 32 | 顺序队列本身是一种数组表示。在队列的顺序存储结构中,除了用一组连续的存储单元依次存放从队列头到队列尾的元素之外,尚需附设两个指针 front 和 rear 分别指示队列头元素及队列尾元素的位置。为了在C语言中描述方便,通常有如下约定:初始化创建空队列时,令 front = rear = 0,每当插入新的队列尾元素时,“尾指针增 1”;每当删除队列头元素时,“头指针增 1”;因此,在非空队列下,头指针始终指向队列头元素,而尾指针始终指向队列尾元素的下一个位置,如图所示: 33 | ![301.顺序队列示意图](./images/301.顺序队列示意图.png) 34 | 35 | 假设当前队列分配最大空间为6,则当队列处于上图(d)的状态时,不可再继续插入新的队尾元素,否则会因为数组越界而导致程序代码被破坏。然而此时又不宜进行存储再分配扩大数组空间,因为队列的实际可用空间并未占满。一个巧妙的办法是将顺序队列臆造为一个环状的空间,如图所示,称之为循环队列: 36 | ![302.循环队列示意图](./images/302.循环队列示意图.png) 37 | ![303.循环队列](./images/303.循环队列.jpg) 38 | 39 | 如图,指针和队列之间的关系不变,上图 (a) 所示循环队列中,队列头元素是 J3 ,队列尾元素是 J5,之后J6,J7和J8相继插入,则队列空间均被占满,如图 (b) 所示,此时 Q.front = Q.rear; 反之,若 J3,J4 和 J5 相继从图 (a) 队列中删除,使队列呈“空”的状态,如图 (c) 所示,此时存在关系为 Q.front = Q.rear, 由此可见只凭等式 Q.front = Q.rear无法判断队列是“空”还是“满”。有两种可处理方式:一种是另外设置一个标志以区别队列是 “空” 还是 “满”;另一种是少用一个元素空间,约定以“队列头指针在队列尾指针的下一位置(指环状的下一位置)”作为队列呈“满”状态的标志。 40 | 41 | 从此分析中可见,在C语言中不能用动态分配的一维数组来实现循环队列,如果用户的应用程序中设有循环队列,则必须为它设定一个最大队列长度,若用户无法预估所用队列的最大长度,则宜采用链式队列。 42 | 43 | 44 | ### 2.1 顺序队列为什么是循环队列 45 | 46 | 循环队列是针对顺序队列中最大内存空间有限,当队列处于上图(d)的状态时,不可再继续插入新的队尾元素,否则会因为数组越界而导致程序代码被破坏。然而此时又不宜进行存储再分配扩大数组空间,因为队列的实际可用空间并未占满的问题的一种合理的解决方案。 47 | 48 | ### 2.2 一共需要几个参数,分别是什么含义 49 | 50 | **front && rear** 51 | 不同场合下含义不同。 52 | 1. 队列初始化 -- front 和 rear 的值都是零 53 | 2. 队列非空 -- front 代表队列的第一个元素,rear 代表队列的最后一个有效元素的下一个元素 54 | 3. 队列为空 -- front 和 rear 相等,但不一定是零 55 | 56 | ### 2.3 入队伪算法 57 | 58 | 尾部入队,分两步完成 59 | 1. 将值存入r所代表的位置 60 | 2. 错误写法 r = r + 1; 正确写法: r = (r + 1) % 数组的长度 【n-1对n取余,结果就是n-1】 61 | 62 | ### 2.4 出队伪算法 63 | 64 | 头部出队,分两步完成 65 | 1. 将f出队的值保存起来(可以根据具体需求确定是否要保存) 66 | 2. f 的指针变动正确写法: f = (f + 1) % 数组的长度 【n-1对n取余,结果就是n-1】 67 | 68 | ### 2.5 如何判断循环队列是否为空 69 | 70 | 如果front == rear ,则该队列一定为空 71 | 72 | ### 2.6 如何判断循环队列已满 73 | 74 | 预备知识: 75 | front 的值可能比 rear 大 76 | front 的值也可能比 rear 小 77 | 当然两者也完全可能相等 78 | 79 | 判断已满两种方式: 80 | 1. 多增加一个标识参数 81 | 2. 少用数组中的一个元素【可以直接用两个参数,通常使用第二种方式】 82 | 如果r 和 f 的值紧挨着,则标识队列已满 83 | C语言标识就是: 84 | if ( (r+1)%数组长度 == f) 85 | 队列已满 86 | else 87 | 队列未满 88 | 89 | 90 | ### 2.7 什么时候该使用顺序队列?什么时候该使用链式队列? 91 | 92 | 如果用户的应用程序中设有循环队列,则必须为它设定一个最大队列长度,若用户无法预估所用队列的最大长度,则宜采用链式队列 93 | 94 | ## 3. 队列的伪算法和实现 95 | 96 | 此小节实现的是一个最大队列长度为 6 的环形队列,下面是本队列的定义和相关实现。 97 | 98 | 队列类型的定义 99 | 100 | ```c 101 | #define kQueueMaxLength 6 // 假设最大长度为 6 102 | typedef struct Queue{ 103 | int * pBase; // 队列中操作的数组 104 | int front; // 队头 105 | int rear; // 对尾 106 | }QUEUE; 107 | ``` 108 | 109 | 队列的初始化 110 | 111 | ```c 112 | /** 113 | 初始化队列 114 | @param pQueue 要被初始化队列地址 115 | */ 116 | void init_queue(QUEUE *pQueue){ 117 | pQueue->pBase = (int *)malloc(sizeof(int) * kQueueMaxLength); // 初始化,pBase指向长度6的 int* 数组 118 | pQueue->front = pQueue->rear = 0; 119 | } 120 | ``` 121 | 122 | 元素入队 123 | 124 | ```c 125 | /** 126 | 入队 127 | 128 | @param pQueue 要入队的队列地址 129 | @param val 入队元素的值 130 | @return 入队成功/失败 131 | */ 132 | bool en_queue(QUEUE *pQueue , int val){ 133 | 134 | if (full_queue(pQueue)) { // 队列已满,直接返回入队失败 135 | return false; 136 | }else 137 | { // 队列未满,执行入队操作 138 | 139 | // 1.元素插入数组中 140 | pQueue->pBase[pQueue->rear] = val; 141 | // 2.队头队尾的表示 142 | pQueue->rear = (pQueue->rear + 1) % kQueueMaxLength; 143 | 144 | return true; 145 | } 146 | } 147 | ``` 148 | 149 | 元素出队 150 | 151 | ```c 152 | /** 153 | 出队 154 | 155 | @param pQueue 要出队队列地址 156 | @param val 被出队元素地址 157 | @return 出队成功/失败 158 | */ 159 | bool de_queue(QUEUE *pQueue , int *val){ 160 | 161 | if (empty_queue(pQueue)) { // 如果是空队列,直接出队失败 162 | return false; 163 | }else 164 | { 165 | // 出队->保存被出队元素的值 166 | *val = pQueue->pBase[pQueue->front]; 167 | // 修改队头位置 168 | pQueue->front = (pQueue->front + 1) % kQueueMaxLength; 169 | 170 | } 171 | return true; 172 | } 173 | ``` 174 | 175 | 遍历队列 176 | 177 | ```c 178 | /** 179 | 遍历队列 180 | 181 | @param pQueue 要遍历的队列的地址 182 | */ 183 | void tranverce_queue(QUEUE *pQueue){ 184 | 185 | int i = pQueue->front; 186 | int lenght = 0; 187 | while (i != pQueue->rear) { 188 | lenght ++; 189 | i = (i + 1) % kQueueMaxLength; 190 | } 191 | printf("队列中共有 %d 个元素\n",lenght); 192 | 193 | i = pQueue->front; 194 | while (i != pQueue->rear) { 195 | 196 | printf("第 %d 个元素为 %d\n",i + 1,pQueue->pBase[i]); 197 | i = (i + 1) % kQueueMaxLength; 198 | } 199 | } 200 | ``` 201 | 202 | 主函数中使用队列 203 | 204 | ```c 205 | int main() { 206 | 207 | QUEUE q; // 声明队列q 208 | init_queue(&q); // 初始化队列q 209 | 210 | en_queue(&q, 2); // 插入元素 211 | en_queue(&q, 21); // 插入元素 212 | en_queue(&q, 3); // 插入元素 213 | en_queue(&q, 4); // 插入元素 214 | en_queue(&q, 5); // 插入元素 215 | en_queue(&q, 6); // 插入元素 216 | en_queue(&q, 7); // 插入元素 217 | en_queue(&q, 8); // 插入元素 218 | 219 | tranverce_queue(&q); //遍历队列 220 | 221 | int i; 222 | bool b; 223 | b = de_queue(&q, &i); // 出队 224 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 225 | 226 | b = de_queue(&q, &i); // 出队 227 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 228 | 229 | b = de_queue(&q, &i); // 出队 230 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 231 | 232 | tranverce_queue(&q); //遍历队列 233 | 234 | return 0; 235 | } 236 | ``` 237 | 238 | 239 | ## 4. 小结 240 | 241 | 队列主要应用在和时间有关的操作。 242 | 243 | 常见的例子如现实生活中排队买票,银行排队处理事情。再如操作系统中执行队列,等待队列。又如我们在编写程序过程中的多线程编程,也需要通过队列来管理线程的访问顺序等。 244 | 245 | 246 | 247 | 文中代码地址:[https://github.com/xiaoyouPrince/DataStructure](https://github.com/xiaoyouPrince/DataStructure) 248 | 249 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/01.结构体和指针/CPointer.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B4F466841FDD8084001D9D40 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B4F466831FDD8084001D9D40 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | B4F4667E1FDD8084001D9D40 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | B4F466801FDD8084001D9D40 /* CPointer */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = CPointer; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B4F466831FDD8084001D9D40 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | B4F4667D1FDD8084001D9D40 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | B4F466771FDD8084001D9D40 = { 42 | isa = PBXGroup; 43 | children = ( 44 | B4F466821FDD8084001D9D40 /* CPointer */, 45 | B4F466811FDD8084001D9D40 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | B4F466811FDD8084001D9D40 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B4F466801FDD8084001D9D40 /* CPointer */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | B4F466821FDD8084001D9D40 /* CPointer */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B4F466831FDD8084001D9D40 /* main.m */, 61 | ); 62 | path = CPointer; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | B4F4667F1FDD8084001D9D40 /* CPointer */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = B4F466871FDD8084001D9D40 /* Build configuration list for PBXNativeTarget "CPointer" */; 71 | buildPhases = ( 72 | B4F4667C1FDD8084001D9D40 /* Sources */, 73 | B4F4667D1FDD8084001D9D40 /* Frameworks */, 74 | B4F4667E1FDD8084001D9D40 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = CPointer; 81 | productName = CPointer; 82 | productReference = B4F466801FDD8084001D9D40 /* CPointer */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | B4F466781FDD8084001D9D40 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0910; 92 | ORGANIZATIONNAME = XiaoYou; 93 | TargetAttributes = { 94 | B4F4667F1FDD8084001D9D40 = { 95 | CreatedOnToolsVersion = 9.1; 96 | ProvisioningStyle = Automatic; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = B4F4667B1FDD8084001D9D40 /* Build configuration list for PBXProject "CPointer" */; 101 | compatibilityVersion = "Xcode 8.0"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = B4F466771FDD8084001D9D40; 108 | productRefGroup = B4F466811FDD8084001D9D40 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | B4F4667F1FDD8084001D9D40 /* CPointer */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | B4F4667C1FDD8084001D9D40 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | B4F466841FDD8084001D9D40 /* main.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | B4F466851FDD8084001D9D40 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 144 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 145 | CLANG_WARN_EMPTY_BODY = YES; 146 | CLANG_WARN_ENUM_CONVERSION = YES; 147 | CLANG_WARN_INFINITE_RECURSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 150 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 152 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 153 | CLANG_WARN_STRICT_PROTOTYPES = YES; 154 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 155 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 156 | CLANG_WARN_UNREACHABLE_CODE = YES; 157 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 158 | CODE_SIGN_IDENTITY = "Mac Developer"; 159 | COPY_PHASE_STRIP = NO; 160 | DEBUG_INFORMATION_FORMAT = dwarf; 161 | ENABLE_STRICT_OBJC_MSGSEND = YES; 162 | ENABLE_TESTABILITY = YES; 163 | GCC_C_LANGUAGE_STANDARD = gnu11; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_NO_COMMON_BLOCKS = YES; 166 | GCC_OPTIMIZATION_LEVEL = 0; 167 | GCC_PREPROCESSOR_DEFINITIONS = ( 168 | "DEBUG=1", 169 | "$(inherited)", 170 | ); 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.13; 178 | MTL_ENABLE_DEBUG_INFO = YES; 179 | ONLY_ACTIVE_ARCH = YES; 180 | SDKROOT = macosx; 181 | }; 182 | name = Debug; 183 | }; 184 | B4F466861FDD8084001D9D40 /* Release */ = { 185 | isa = XCBuildConfiguration; 186 | buildSettings = { 187 | ALWAYS_SEARCH_USER_PATHS = NO; 188 | CLANG_ANALYZER_NONNULL = YES; 189 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 195 | CLANG_WARN_BOOL_CONVERSION = YES; 196 | CLANG_WARN_COMMA = YES; 197 | CLANG_WARN_CONSTANT_CONVERSION = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 208 | CLANG_WARN_STRICT_PROTOTYPES = YES; 209 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 211 | CLANG_WARN_UNREACHABLE_CODE = YES; 212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 213 | CODE_SIGN_IDENTITY = "Mac Developer"; 214 | COPY_PHASE_STRIP = NO; 215 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 216 | ENABLE_NS_ASSERTIONS = NO; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu11; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | MACOSX_DEPLOYMENT_TARGET = 10.13; 227 | MTL_ENABLE_DEBUG_INFO = NO; 228 | SDKROOT = macosx; 229 | }; 230 | name = Release; 231 | }; 232 | B4F466881FDD8084001D9D40 /* Debug */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | CODE_SIGN_STYLE = Automatic; 236 | DEVELOPMENT_TEAM = SLUU2646N5; 237 | PRODUCT_NAME = "$(TARGET_NAME)"; 238 | }; 239 | name = Debug; 240 | }; 241 | B4F466891FDD8084001D9D40 /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | CODE_SIGN_STYLE = Automatic; 245 | DEVELOPMENT_TEAM = SLUU2646N5; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | }; 248 | name = Release; 249 | }; 250 | /* End XCBuildConfiguration section */ 251 | 252 | /* Begin XCConfigurationList section */ 253 | B4F4667B1FDD8084001D9D40 /* Build configuration list for PBXProject "CPointer" */ = { 254 | isa = XCConfigurationList; 255 | buildConfigurations = ( 256 | B4F466851FDD8084001D9D40 /* Debug */, 257 | B4F466861FDD8084001D9D40 /* Release */, 258 | ); 259 | defaultConfigurationIsVisible = 0; 260 | defaultConfigurationName = Release; 261 | }; 262 | B4F466871FDD8084001D9D40 /* Build configuration list for PBXNativeTarget "CPointer" */ = { 263 | isa = XCConfigurationList; 264 | buildConfigurations = ( 265 | B4F466881FDD8084001D9D40 /* Debug */, 266 | B4F466891FDD8084001D9D40 /* Release */, 267 | ); 268 | defaultConfigurationIsVisible = 0; 269 | defaultConfigurationName = Release; 270 | }; 271 | /* End XCConfigurationList section */ 272 | }; 273 | rootObject = B4F466781FDD8084001D9D40 /* Project object */; 274 | } 275 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/01.结构体和指针/CPointer.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/01.结构体和指针/CPointer.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/01.结构体和指针/CPointer.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/01.结构体和指针/CPointer.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CPointer.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/01.结构体和指针/CPointer/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CPointer 4 | // 5 | // Created by 渠晓友 on 2017/12/10. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef struct Student{ // 使用 typedef 声明一个 struct Student 类型的结构体,别名为 myStudent 12 | int age; 13 | char * name; 14 | char name2[100]; 15 | double height; 16 | }myStudent; 17 | 18 | // 直接传递 struct Student st 整个结构体数据,耗时 && 浪费内存空间 19 | void func(struct Student st); 20 | // 直接传递 只占用 4 byte 的指针,省时效率也高 <推荐用法> 21 | void func2(struct Student * pst); 22 | void test1(void); 23 | #pragma mark -- 结构体和指针的使用 ……………………^^^^^^^^^^ 24 | 25 | void test2(void); 26 | 27 | #pragma mark -- 动态内存的创建和释放 …………^^^^^^^^^^ 28 | 29 | myStudent * createStudent(void); 30 | void showStudent(myStudent *); 31 | void test3(void); 32 | 33 | int main(int argc, const char * argv[]) { 34 | @autoreleasepool { 35 | 36 | 37 | //test1(); 38 | 39 | //test2(); 40 | 41 | test3(); 42 | 43 | } 44 | return 0; 45 | } 46 | 47 | 48 | #pragma mark -- 结构体使用 49 | void test1(void) 50 | { 51 | // struct Student s = {12,"xiaoyou",1.73}; 52 | // 53 | // printf(" age = %d \n name = %s \n height = %.2f \n",s.age,s.name,s.height); 54 | // 55 | // s.age = 21; 56 | // s.name = "xiaozhu"; 57 | // strcpy(s.name2, "zhangwangdsd"); // 字符串拷贝 58 | // s.height = 1.70; 59 | // 60 | // printf(" age = %d \n name = %s \n height = %.2f \n",s.age,s.name,s.height); 61 | // 62 | // printf(" name2 = %s \n",s.name2); 63 | 64 | 65 | myStudent ss = {12,"xiaoyou",1.73}; 66 | printf(" age = %d \n name = %s \n height = %.2f \n",ss.age,ss.name,ss.height); 67 | 68 | 69 | struct Student *pst = &ss; 70 | pst -> name = "my new name"; 71 | 72 | printf(" name = %s\n",pst->name); 73 | printf(" name = %s\n",(*pst).name); 74 | 75 | // pst -> name 等价于 (*pst).name , 76 | // 而(*pst).name 又等价于 ss.name 77 | // 所以 pst -> name 等价于 ss.name 78 | 79 | 80 | func(ss); 81 | 82 | func2(&ss); 83 | } 84 | 85 | 86 | // 直接传递 struct Student st 整个结构体数据,耗时 && 浪费内存空间 87 | void func(struct Student st){ 88 | 89 | printf("age = %d \n name = %s",st.age,st.name); 90 | } 91 | 92 | // 直接传递 只占用 4 byte 的指针,省时效率也高 <推荐用法> 93 | void func2(struct Student * pst){ 94 | 95 | printf("age = %d \n name = %s",(*pst).age,(*pst).name); 96 | printf("age = %d \n name = %s",pst->age,pst->name); 97 | } 98 | 99 | #pragma mark -- 动态内存的创建和释放 100 | 101 | void test2(void) 102 | { 103 | int len; 104 | printf("请输入你要动态创建的数组长度:"); 105 | scanf("%d",&len); 106 | 107 | int *pArr = (int *)malloc(len); // 动态创建数组 108 | *pArr = 4; // 相当于 a[0] = 4; 这里 pArr 就等于数组首地址,等于数组名 109 | pArr[2] = 5; // 相当于 a[2] = 5; 110 | 111 | printf("pArr[0] = %d \npArr[2] = %d\n",pArr[0],pArr[2]); 112 | 113 | free(pArr); // 使用完毕,释放对应的数组空间 114 | } 115 | 116 | #pragma mark -- 跨函数使用内存 117 | 118 | myStudent * createStudent(void) 119 | { 120 | myStudent *p = (myStudent *)malloc(sizeof(myStudent)); 121 | p->age = 20; 122 | p->name = "xiaoyou"; 123 | return p; 124 | } 125 | void showStudent(myStudent *p) 126 | { 127 | printf("student.age = %d \nstudent.name = %s\n",p->age,p->name); 128 | } 129 | void test3(void) 130 | { 131 | myStudent *p = createStudent(); 132 | showStudent(p); 133 | } 134 | 135 | 136 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B444AEC31FDF80AC00365280 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B444AEC21FDF80AC00365280 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | B444AEBD1FDF80AC00365280 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | B444AEBF1FDF80AC00365280 /* 数组 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "数组"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B444AEC21FDF80AC00365280 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | B444AEBC1FDF80AC00365280 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | B444AEB61FDF80AC00365280 = { 42 | isa = PBXGroup; 43 | children = ( 44 | B444AEC11FDF80AC00365280 /* 数组 */, 45 | B444AEC01FDF80AC00365280 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | B444AEC01FDF80AC00365280 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B444AEBF1FDF80AC00365280 /* 数组 */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | B444AEC11FDF80AC00365280 /* 数组 */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B444AEC21FDF80AC00365280 /* main.m */, 61 | ); 62 | path = "数组"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | B444AEBE1FDF80AC00365280 /* 数组 */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = B444AEC61FDF80AC00365280 /* Build configuration list for PBXNativeTarget "数组" */; 71 | buildPhases = ( 72 | B444AEBB1FDF80AC00365280 /* Sources */, 73 | B444AEBC1FDF80AC00365280 /* Frameworks */, 74 | B444AEBD1FDF80AC00365280 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "数组"; 81 | productName = "数组"; 82 | productReference = B444AEBF1FDF80AC00365280 /* 数组 */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | B444AEB71FDF80AC00365280 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0910; 92 | ORGANIZATIONNAME = XiaoYou; 93 | TargetAttributes = { 94 | B444AEBE1FDF80AC00365280 = { 95 | CreatedOnToolsVersion = 9.1; 96 | ProvisioningStyle = Automatic; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = B444AEBA1FDF80AC00365280 /* Build configuration list for PBXProject "数组" */; 101 | compatibilityVersion = "Xcode 8.0"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = B444AEB61FDF80AC00365280; 108 | productRefGroup = B444AEC01FDF80AC00365280 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | B444AEBE1FDF80AC00365280 /* 数组 */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | B444AEBB1FDF80AC00365280 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | B444AEC31FDF80AC00365280 /* main.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | B444AEC41FDF80AC00365280 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 144 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 145 | CLANG_WARN_EMPTY_BODY = YES; 146 | CLANG_WARN_ENUM_CONVERSION = YES; 147 | CLANG_WARN_INFINITE_RECURSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 150 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 152 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 153 | CLANG_WARN_STRICT_PROTOTYPES = YES; 154 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 155 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 156 | CLANG_WARN_UNREACHABLE_CODE = YES; 157 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 158 | CODE_SIGN_IDENTITY = "Mac Developer"; 159 | COPY_PHASE_STRIP = NO; 160 | DEBUG_INFORMATION_FORMAT = dwarf; 161 | ENABLE_STRICT_OBJC_MSGSEND = YES; 162 | ENABLE_TESTABILITY = YES; 163 | GCC_C_LANGUAGE_STANDARD = gnu11; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_NO_COMMON_BLOCKS = YES; 166 | GCC_OPTIMIZATION_LEVEL = 0; 167 | GCC_PREPROCESSOR_DEFINITIONS = ( 168 | "DEBUG=1", 169 | "$(inherited)", 170 | ); 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.13; 178 | MTL_ENABLE_DEBUG_INFO = YES; 179 | ONLY_ACTIVE_ARCH = YES; 180 | SDKROOT = macosx; 181 | }; 182 | name = Debug; 183 | }; 184 | B444AEC51FDF80AC00365280 /* Release */ = { 185 | isa = XCBuildConfiguration; 186 | buildSettings = { 187 | ALWAYS_SEARCH_USER_PATHS = NO; 188 | CLANG_ANALYZER_NONNULL = YES; 189 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 195 | CLANG_WARN_BOOL_CONVERSION = YES; 196 | CLANG_WARN_COMMA = YES; 197 | CLANG_WARN_CONSTANT_CONVERSION = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 208 | CLANG_WARN_STRICT_PROTOTYPES = YES; 209 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 211 | CLANG_WARN_UNREACHABLE_CODE = YES; 212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 213 | CODE_SIGN_IDENTITY = "Mac Developer"; 214 | COPY_PHASE_STRIP = NO; 215 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 216 | ENABLE_NS_ASSERTIONS = NO; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu11; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | MACOSX_DEPLOYMENT_TARGET = 10.13; 227 | MTL_ENABLE_DEBUG_INFO = NO; 228 | SDKROOT = macosx; 229 | }; 230 | name = Release; 231 | }; 232 | B444AEC71FDF80AC00365280 /* Debug */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | CODE_SIGN_STYLE = Automatic; 236 | DEVELOPMENT_TEAM = SLUU2646N5; 237 | PRODUCT_NAME = "$(TARGET_NAME)"; 238 | }; 239 | name = Debug; 240 | }; 241 | B444AEC81FDF80AC00365280 /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | CODE_SIGN_STYLE = Automatic; 245 | DEVELOPMENT_TEAM = SLUU2646N5; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | }; 248 | name = Release; 249 | }; 250 | /* End XCBuildConfiguration section */ 251 | 252 | /* Begin XCConfigurationList section */ 253 | B444AEBA1FDF80AC00365280 /* Build configuration list for PBXProject "数组" */ = { 254 | isa = XCConfigurationList; 255 | buildConfigurations = ( 256 | B444AEC41FDF80AC00365280 /* Debug */, 257 | B444AEC51FDF80AC00365280 /* Release */, 258 | ); 259 | defaultConfigurationIsVisible = 0; 260 | defaultConfigurationName = Release; 261 | }; 262 | B444AEC61FDF80AC00365280 /* Build configuration list for PBXNativeTarget "数组" */ = { 263 | isa = XCConfigurationList; 264 | buildConfigurations = ( 265 | B444AEC71FDF80AC00365280 /* Debug */, 266 | B444AEC81FDF80AC00365280 /* Release */, 267 | ); 268 | defaultConfigurationIsVisible = 0; 269 | defaultConfigurationName = Release; 270 | }; 271 | /* End XCConfigurationList section */ 272 | }; 273 | rootObject = B444AEB71FDF80AC00365280 /* Project object */; 274 | } 275 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/02.数组/数组.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 数组.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.数组/数组/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 数组 4 | // 5 | // Created by 渠晓友 on 2017/12/12. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | // 定义个数组 12 | typedef struct Array { 13 | int length; // 数组长度 14 | int count; // 数组当前元素数 count 15 | int *pBase; // 数组的首字节地址 16 | }* PMyArray,MyArray; //两个别名,PMyArray 类似java中类名,定义的对象不带 * , MyArray类似于OC中的类型,定义的对象带 * 。 17 | 18 | /** 初始化数组*/ 19 | void init_Arr(MyArray *pArr, int len); 20 | /** 追加数组*/ 21 | bool append_Arr(MyArray *pArr, int value); 22 | /** 插入数组*/ 23 | bool insert_Arr(MyArray *pArr, int index , int value); 24 | /** 删除数组*/ 25 | bool delete_Arr(MyArray *pArr, int index , int * pVal); 26 | /** 是否满载*/ 27 | bool is_full(MyArray *pArr); 28 | /** 是否为空*/ 29 | bool is_empty(MyArray *pArr); 30 | /** 排序数组*/ 31 | void sort_Arr(MyArray *pArr); 32 | /** 展示数组*/ 33 | void show_Arr(MyArray *pArr); 34 | /** 倒序数组*/ 35 | void inversion_Arr(MyArray *pArr); 36 | 37 | /** 获取一个默认初始化的数组*/ 38 | MyArray * get_Arr(void); 39 | 40 | 41 | int main(void) { 42 | 43 | 44 | MyArray arr; // 声明 45 | int len = 6; // 定义数组长度 46 | init_Arr(&arr,len); // 初始化 47 | 48 | // 添加元素 49 | int time = 0; 50 | while (time < len) { 51 | append_Arr(&arr, 100 + time); 52 | time++; 53 | } 54 | 55 | 56 | insert_Arr(&arr, 6, 200); // 插入元素 57 | insert_Arr(&arr, 7, 300); 58 | insert_Arr(&arr, arr.count, 400); 59 | insert_Arr(&arr, 0, 500); 60 | insert_Arr(&arr, 3, 600); 61 | 62 | show_Arr(&arr); // 打印数组元素 63 | 64 | int val; 65 | //delete_Arr(&arr, 3 ,NULL); // 删除第三个元素 66 | delete_Arr(&arr, 3 ,&val); 67 | printf("被删除的元素是 %d \n",val); 68 | 69 | 70 | show_Arr(&arr); // 打印数组元素 71 | 72 | inversion_Arr(&arr); // 倒序排列一下 73 | 74 | show_Arr(&arr); // 打印数组元素 75 | 76 | sort_Arr(&arr); // 排序数组 77 | 78 | show_Arr(&arr); // 打印数组元素 79 | 80 | 81 | 82 | #pragma mark -- OOP 83 | 84 | MyArray * array = get_Arr(); 85 | 86 | printf("打印一个自己实现的模拟面向对象的方式\n"); 87 | show_Arr(array); // 打印数组元素 88 | 89 | 90 | int val1 = array->pBase[array->count] ; 91 | int val2 = array->pBase[array->count - 1]; 92 | printf("val1 = %d val2 = %d\n",val1,val2); 93 | 94 | 95 | MyArray * array2 = get_Arr(); 96 | 97 | printf("打印一个自己实现的模拟面向对象的方式\n"); 98 | show_Arr(array2); // 打印数组元素 99 | append_Arr(array2, 20); 100 | append_Arr(array2, 30); 101 | insert_Arr(array2, 0, 20); 102 | insert_Arr(array2, 1, 30); 103 | 104 | 105 | show_Arr(array2); 106 | 107 | 108 | 109 | int val3 = array->pBase[array2->count] ; 110 | int val4 = array->pBase[array2->count - 1]; 111 | printf("val3 = %d val4 = %d\n",val3,val4); 112 | 113 | 114 | printf("array1 address is %p\n",array); 115 | printf("array1 address is %p\n",&array); 116 | printf("array2 address is %p\n",array2); 117 | printf("array2 address is %p\n",&array2); 118 | 119 | 120 | // 类似于 OC 中的面向对象用法 121 | MyArray * array3 = get_Arr(); 122 | printf("array3 address is %p\n",array3); 123 | printf("array3 address is %p\n",&array3); 124 | show_Arr(array3); 125 | 126 | 127 | // 类似于 java 中的面向对象用法 128 | PMyArray myArray4 = get_Arr(); 129 | printf("array4 address is %p\n",myArray4); 130 | printf("array4 address is %p\n",&myArray4); 131 | show_Arr(myArray4); 132 | 133 | // NSMutableArray *arrayM = [NSMutableArray array]; 134 | // int time = 0; 135 | // while (time < 10) { 136 | // [arrayM addObject:@(time + 100)]; 137 | // time++; 138 | // } 139 | // 140 | // [arrayM insertObject:@"你好" atIndex:4]; 141 | // 142 | // NSLog(@"arrayM = %@",arrayM); 143 | 144 | 145 | return 0; 146 | } 147 | 148 | 149 | /** 150 | 初始化数组 151 | 152 | @param pArr 要初始化的数组指针 153 | @param len 初始化的数组长度 154 | */ 155 | void init_Arr(MyArray *pArr,int len){ 156 | 157 | (*pArr).pBase = (int *)malloc(sizeof(int) * len); // 先分配一段内存空间,长度为 len * int长度。 158 | if(pArr->pBase == NULL) 159 | { 160 | printf("内存分配失败,初始化失败\n"); 161 | exit(-1); // 终止程序 162 | }else 163 | { 164 | pArr->length = len; 165 | pArr->count = 0; 166 | } 167 | 168 | return; 169 | } 170 | 171 | /** 172 | 往数组尾部添加元素 173 | 174 | @param pArr 数组指针 175 | @param value 要添加的元素值 176 | @return 添加成功/失败 177 | */ 178 | bool append_Arr(MyArray *pArr,int value){ 179 | 180 | if (!is_full(pArr)) { 181 | // 数组未满,添加 182 | pArr->pBase[pArr->count] = value; 183 | pArr->count++; 184 | return true; 185 | 186 | }else{ 187 | printf("数组已经满了,无法从尾部追加元素,请尝试从前面插入\n"); 188 | return false; 189 | } 190 | 191 | } 192 | 193 | 194 | /** 195 | 实现数组插入 196 | 197 | 1. 判断插入下标是否越界 198 | 2. 如果插入前数组已经满了,就增大一个长度,重新插入 199 | 3. 如果插入前数组未满 200 | 3.1 当插入位置小于最大元素下标,先把要插入目标点后面的元素往后移动一个单位。 如在{1,2,4,5}中第3个位置插入3,结果为{1,2,3,4,5} 201 | 3.2 当插入位置大于等于最大元素下标,直接在原来数组后面add最后一个元素。 如在{1,2}中第5个位置插入 3 结果为{1,2,3} 202 | 203 | @param pArr 要操作的数组的指针 204 | @param index 要插入的index 即下标 205 | @param value 要插入的值 206 | @return 返回插入成功/失败 207 | */ 208 | bool insert_Arr(MyArray *pArr, int index , int value){ 209 | 210 | if (index > pArr->length || index < 0) { 211 | printf("数组插入位置越界\n"); 212 | return false; 213 | } 214 | 215 | if (is_full(pArr)) { 216 | 217 | // 如果满了就长度+1,然后执行未满的情况(这里成了递归了就) 218 | pArr->length ++; 219 | return insert_Arr(pArr, index, value); 220 | 221 | }else 222 | { 223 | // 未满可以插入 224 | if (index < pArr->count) { 225 | // 1. 原来元素先往后移 226 | for (int i = 0 ; i < (pArr->count - index); i++) { 227 | pArr->pBase[pArr->count - i] = pArr->pBase[pArr->count - i - 1]; 228 | } 229 | 230 | // 2. 插入的元素直接插入对应位置 231 | pArr->pBase[index] = value; 232 | pArr->count ++; 233 | }else 234 | { 235 | // 插入到最后面即可 236 | append_Arr(pArr, value); 237 | } 238 | 239 | return true; 240 | } 241 | } 242 | 243 | /** 244 | 实现数组删除某个元素 245 | 并可以从外部获得被删除元素的值 246 | 247 | 1. 判断删除下标是否越界 248 | 2. 判断原数组是否为空 249 | 3. 如果删除前先保存对应 index 的值赋值给外部变量 250 | 把要删除目标点后面的元素往前移动一个单位。 如在{1,2,3,4,5}中第3个位置删除3,结果为{1,2,4,5} 251 | 252 | @param pArr 要操作的数组的指针 253 | @param index 要伤处的index 即下标 254 | @param pVal 要删除值的地址 255 | @return 返回删除成功/失败 256 | */ 257 | bool delete_Arr(MyArray *pArr , int index ,int *pVal) 258 | { 259 | if (is_empty(pArr)) { 260 | return false; 261 | } 262 | 263 | if (index < 0 || index >= pArr->count) { 264 | printf("要删除的位置下边越界\n"); 265 | return false; 266 | } 267 | 268 | 269 | if (pVal == NULL) { 270 | // 这里是用户没传要接收被删除元素的数组,直接过 271 | }else 272 | { 273 | *pVal = pArr->pBase[index]; // 要删除的值,赋值给外部的变量,通知外部 274 | } 275 | 276 | 277 | // 所有后面的元素,均向前移动一个单位 278 | // int time = pArr->count - index - 1; 279 | // for (int i = 0; i < time; i++) { 280 | // pArr->pBase[index + i] = pArr->pBase[index + i + 1]; 281 | // } 282 | // pArr->count --; 283 | 284 | // 同上两个算法思路,实质相同,都是后面的元素前移动一个单位 285 | for (int i = index; i <= pArr->count - 1; i++) { 286 | pArr->pBase[i] = pArr->pBase[i + 1]; 287 | } 288 | pArr->count --; 289 | 290 | return true; 291 | } 292 | 293 | /** 294 | 判断数组是否为空 295 | 296 | @param pArr 数组指针 297 | @return 结果值 298 | */ 299 | bool is_empty(MyArray *pArr){ 300 | 301 | if (pArr->count == 0) { 302 | return true; 303 | }else 304 | { 305 | return false; 306 | } 307 | } 308 | 309 | /** 310 | 判断数组是否为满载 311 | 312 | @param pArr 数组指针 313 | @return 结果值 314 | */ 315 | bool is_full(MyArray *pArr){ 316 | 317 | if (pArr->count < pArr->length) { 318 | return false; 319 | }else 320 | { 321 | return true; 322 | } 323 | } 324 | 325 | 326 | 327 | /** 328 | 打印有效数组元素 329 | 330 | @param pArr 数组指针 331 | */ 332 | void show_Arr(MyArray *pArr){ 333 | 334 | if (is_empty(pArr)) { 335 | // 数组为空 336 | printf("此数组为空数组\n"); 337 | }else { 338 | // printf("base = %p,\nlength = %d,\ncount = %d\n",pArr->pBase,pArr->length,pArr->count); 339 | // 打印所有数据 340 | for (int i = 0; i < pArr->count; i++) { // 只打印有效的元素 341 | printf("%d ",pArr->pBase[i]); // 数组对应的元素 342 | } 343 | printf("\n"); 344 | } 345 | } 346 | 347 | /** 348 | 倒序排列数组 349 | 350 | @param pArr 要被倒序的数组指针 351 | */ 352 | void inversion_Arr(MyArray *pArr){ 353 | 354 | if (pArr->count <= 1) return; 355 | 356 | // int time = 0; 357 | // if (pArr->count % 2 == 0) { 358 | // // 偶数数组 359 | // time = pArr->count / 2; // 交换次数 360 | // }else{ 361 | // // 奇数数组 362 | // time = pArr->count / 2; 363 | // } 364 | 365 | // 这里直接取商就行 366 | int time = pArr->count / 2; 367 | for (int i = 0 ; i < time; i++) { 368 | 369 | int temp = pArr->pBase[i]; 370 | pArr->pBase[i] = pArr->pBase[pArr->count - 1 - i]; 371 | pArr->pBase[pArr->count - 1 - i] = temp; 372 | } 373 | } 374 | 375 | 376 | /** 377 | 排序数组(降序) 378 | 379 | 如果升序可以直接重新调用一次 inversion_Arr 函数 380 | 381 | @param pArr 要被排序的数组指针 382 | */ 383 | void sort_Arr(MyArray *pArr){ 384 | 385 | int i , j , temp; 386 | 387 | for (i = 0; i < pArr->count; i++) { 388 | for (j = i + 1; j < pArr->count; j++) { 389 | if (pArr->pBase[i] < pArr->pBase[j]) { 390 | temp = pArr->pBase[i]; 391 | pArr->pBase[i] = pArr->pBase[j]; 392 | pArr->pBase[j] = temp; 393 | } 394 | } 395 | } 396 | } 397 | 398 | 399 | MyArray * get_Arr(void){ 400 | 401 | static MyArray arr; 402 | int length = 1; 403 | init_Arr(&arr, length); 404 | 405 | append_Arr(&arr, 10); 406 | 407 | 408 | // Address of stack memory associated with local variable 'arr' returned 409 | // 这里的意思是在变量在栈区建立的变量地址,当这个函数执行完,整个这个函数的内存就会被释放, 410 | // 所以本来返回的地址在被销毁之前能正常使用,函数调用完成内存被释放之后就变成了一个不知所指向的地址了。 411 | // 所以在外部是访问不到 412 | // 解决办法: 413 | // 可以使用 static 关键字,创建一块全局空间供全局使用(但全局都只有一个了,这样也不利于随意创建对象) 414 | 415 | return &arr; 416 | 417 | } 418 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B444AED61FE1246200365280 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B444AED51FE1246200365280 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | B444AED01FE1246200365280 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | B444AED21FE1246200365280 /* 链表 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "链表"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B444AED51FE1246200365280 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | B444AECF1FE1246200365280 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | B444AEC91FE1246200365280 = { 42 | isa = PBXGroup; 43 | children = ( 44 | B444AED41FE1246200365280 /* 链表 */, 45 | B444AED31FE1246200365280 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | B444AED31FE1246200365280 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B444AED21FE1246200365280 /* 链表 */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | B444AED41FE1246200365280 /* 链表 */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B444AED51FE1246200365280 /* main.m */, 61 | ); 62 | path = "链表"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | B444AED11FE1246200365280 /* 链表 */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = B444AED91FE1246200365280 /* Build configuration list for PBXNativeTarget "链表" */; 71 | buildPhases = ( 72 | B444AECE1FE1246200365280 /* Sources */, 73 | B444AECF1FE1246200365280 /* Frameworks */, 74 | B444AED01FE1246200365280 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "链表"; 81 | productName = "链表"; 82 | productReference = B444AED21FE1246200365280 /* 链表 */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | B444AECA1FE1246200365280 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0910; 92 | ORGANIZATIONNAME = XiaoYou; 93 | TargetAttributes = { 94 | B444AED11FE1246200365280 = { 95 | CreatedOnToolsVersion = 9.1; 96 | ProvisioningStyle = Automatic; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = B444AECD1FE1246200365280 /* Build configuration list for PBXProject "链表" */; 101 | compatibilityVersion = "Xcode 8.0"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = B444AEC91FE1246200365280; 108 | productRefGroup = B444AED31FE1246200365280 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | B444AED11FE1246200365280 /* 链表 */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | B444AECE1FE1246200365280 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | B444AED61FE1246200365280 /* main.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | B444AED71FE1246200365280 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 144 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 145 | CLANG_WARN_EMPTY_BODY = YES; 146 | CLANG_WARN_ENUM_CONVERSION = YES; 147 | CLANG_WARN_INFINITE_RECURSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 150 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 152 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 153 | CLANG_WARN_STRICT_PROTOTYPES = YES; 154 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 155 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 156 | CLANG_WARN_UNREACHABLE_CODE = YES; 157 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 158 | CODE_SIGN_IDENTITY = "Mac Developer"; 159 | COPY_PHASE_STRIP = NO; 160 | DEBUG_INFORMATION_FORMAT = dwarf; 161 | ENABLE_STRICT_OBJC_MSGSEND = YES; 162 | ENABLE_TESTABILITY = YES; 163 | GCC_C_LANGUAGE_STANDARD = gnu11; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_NO_COMMON_BLOCKS = YES; 166 | GCC_OPTIMIZATION_LEVEL = 0; 167 | GCC_PREPROCESSOR_DEFINITIONS = ( 168 | "DEBUG=1", 169 | "$(inherited)", 170 | ); 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.13; 178 | MTL_ENABLE_DEBUG_INFO = YES; 179 | ONLY_ACTIVE_ARCH = YES; 180 | SDKROOT = macosx; 181 | }; 182 | name = Debug; 183 | }; 184 | B444AED81FE1246200365280 /* Release */ = { 185 | isa = XCBuildConfiguration; 186 | buildSettings = { 187 | ALWAYS_SEARCH_USER_PATHS = NO; 188 | CLANG_ANALYZER_NONNULL = YES; 189 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 195 | CLANG_WARN_BOOL_CONVERSION = YES; 196 | CLANG_WARN_COMMA = YES; 197 | CLANG_WARN_CONSTANT_CONVERSION = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 208 | CLANG_WARN_STRICT_PROTOTYPES = YES; 209 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 211 | CLANG_WARN_UNREACHABLE_CODE = YES; 212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 213 | CODE_SIGN_IDENTITY = "Mac Developer"; 214 | COPY_PHASE_STRIP = NO; 215 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 216 | ENABLE_NS_ASSERTIONS = NO; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu11; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | MACOSX_DEPLOYMENT_TARGET = 10.13; 227 | MTL_ENABLE_DEBUG_INFO = NO; 228 | SDKROOT = macosx; 229 | }; 230 | name = Release; 231 | }; 232 | B444AEDA1FE1246200365280 /* Debug */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | CODE_SIGN_STYLE = Automatic; 236 | DEVELOPMENT_TEAM = SLUU2646N5; 237 | PRODUCT_NAME = "$(TARGET_NAME)"; 238 | }; 239 | name = Debug; 240 | }; 241 | B444AEDB1FE1246200365280 /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | CODE_SIGN_STYLE = Automatic; 245 | DEVELOPMENT_TEAM = SLUU2646N5; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | }; 248 | name = Release; 249 | }; 250 | /* End XCBuildConfiguration section */ 251 | 252 | /* Begin XCConfigurationList section */ 253 | B444AECD1FE1246200365280 /* Build configuration list for PBXProject "链表" */ = { 254 | isa = XCConfigurationList; 255 | buildConfigurations = ( 256 | B444AED71FE1246200365280 /* Debug */, 257 | B444AED81FE1246200365280 /* Release */, 258 | ); 259 | defaultConfigurationIsVisible = 0; 260 | defaultConfigurationName = Release; 261 | }; 262 | B444AED91FE1246200365280 /* Build configuration list for PBXNativeTarget "链表" */ = { 263 | isa = XCConfigurationList; 264 | buildConfigurations = ( 265 | B444AEDA1FE1246200365280 /* Debug */, 266 | B444AEDB1FE1246200365280 /* Release */, 267 | ); 268 | defaultConfigurationIsVisible = 0; 269 | defaultConfigurationName = Release; 270 | }; 271 | /* End XCConfigurationList section */ 272 | }; 273 | rootObject = B444AECA1FE1246200365280 /* Project object */; 274 | } 275 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/02.链表/链表.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 链表.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/02.链表/链表/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 链表 4 | // 5 | // Created by 渠晓友 on 2017/12/13. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | typedef struct Node{ // 声明链表 13 | int data; //数据域 14 | struct Node *pNext; // 指针域 15 | }*PNODE,NODE; // PNODE 等价于 struct Node * , NODE 等价于 struct Node 16 | 17 | 18 | /** 创建链表*/ 19 | PNODE creatate_list(void); 20 | /** 遍历链表*/ 21 | void traverse_list(PNODE pHead); 22 | /** 判断是否为空链表*/ 23 | bool isEmpty_list(PNODE pHead); 24 | /** 求链表长度*/ 25 | int length_list(PNODE pHead); 26 | /** 链表排序*/ 27 | void sort_list(PNODE pHead); 28 | /** 链表插入某个元素*/ 29 | bool insert_list(PNODE pHead , int pos , int val); 30 | /** 链表删除某个元素 31 | 当pos <= 1 则删除第一个元素,当pos > 链表长度则返回false,并报告原因 32 | */ 33 | bool delete_list(PNODE pHead , int pos , int * val); 34 | 35 | 36 | int main(void) { 37 | 38 | PNODE pHead = NULL; //栈区定义一个链表 39 | 40 | pHead = creatate_list(); // 创建链表(这次的内存在堆取,所以需要手动最后释放内存) 41 | traverse_list(pHead); // 遍历打印链表 42 | 43 | // bool isEmpty = isEmpty_list(pHead); // 判断是否为空链表 44 | // int len = length_list(pHead); // 计算链表长度 45 | // printf("pHead %s an empty list, its length is %d\n",isEmpty ? "is" : "is not",len); 46 | // 47 | // sort_list(pHead); // 排序 48 | // traverse_list(pHead); // 遍历打印链表 49 | // 50 | // insert_list(pHead, 10, 100); // 插入链表 51 | // traverse_list(pHead); // 遍历打印链表 52 | 53 | int i; 54 | delete_list(pHead, 0, &i); // 删除链表 55 | printf("被删除的节点的值为 %d\n",i); 56 | traverse_list(pHead); // 遍历打印链表 57 | 58 | delete_list(pHead, 1, &i); // 删除链表 59 | printf("被删除的节点的值为 %d\n",i); 60 | traverse_list(pHead); // 遍历打印链表 61 | 62 | delete_list(pHead, 10, &i); // 删除链表 63 | printf("被删除的节点的值为 %d\n",i); 64 | traverse_list(pHead); // 遍历打印链表 65 | 66 | return 0; 67 | } 68 | 69 | 70 | /** 创建列表*/ 71 | PNODE creatate_list(void){ 72 | 73 | // 创建一个值域为空的头结点,给头指针分配内存 74 | PNODE pHead = (PNODE)malloc(sizeof(PNODE)); // 头指针 75 | 76 | if (pHead->pNext == NULL) { 77 | printf("头指针内存分配失败,程序退出\n"); 78 | exit(0); 79 | } 80 | 81 | PNODE pTail = pHead; // 站位尾节点,直接赋值给 pTail,这是栈内存分配; 82 | pTail->pNext = NULL; 83 | 84 | // 创建对应的节点 85 | int len = 0; 86 | int val = 0; 87 | printf("请输入要创建链表的长度:\n"); 88 | scanf("%d",&len); 89 | for (int i = 0; i < len; i++) { 90 | // 根据用户输入的长度创建对应个数的节点 91 | PNODE pNew = (PNODE)malloc(sizeof(NODE)); 92 | 93 | if (pNew == NULL) { 94 | printf("节点分配失败,程序退出\n"); 95 | exit(0); 96 | } 97 | 98 | printf("请输入第 %d 个节点的值",i + 1); 99 | scanf("%d",&val); 100 | 101 | /* 102 | 创建新节点 103 | 新节点赋值给当前最尾节点 pNext 104 | 站位尾节点再次指向新节点 105 | */ 106 | 107 | // 1.保存值和指针,变成完整新节点 108 | pNew->data = val; 109 | pNew->pNext = NULL; 110 | // 2.当前新节点追加到原来尾节点后面 111 | pTail->pNext = pNew; 112 | // 3.新节点变成原来尾节点 113 | pTail = pNew; 114 | 115 | // 从这也能看出堆和栈的区别。堆是一块内存区,里面的内存不会被释放,需要主动过去分配内存和释放,PNODE pTail = (PNODE)malloc(sizeof(PNODE)); 116 | // 栈就是程序里面直接使用的可以不用分配内存就能用的, int a = 20; 117 | 118 | } 119 | 120 | return pHead; // 返回头节点 121 | } 122 | 123 | 124 | /** 遍历列表*/ 125 | void traverse_list(PNODE pHead){ 126 | 127 | // 通过头节点遍历后面节点 128 | PNODE p = pHead->pNext; //获得首节点 129 | while (p != NULL) { 130 | printf("data = %d \n",p->data); 131 | p = p->pNext; 132 | } 133 | 134 | printf("遍历完毕,退出\n"); 135 | return; 136 | } 137 | 138 | /** 判断是否为空链表*/ 139 | bool isEmpty_list(PNODE pHead) 140 | { 141 | if ((*pHead).pNext != NULL) { 142 | return false; 143 | }else{ 144 | return true; 145 | } 146 | } 147 | 148 | /** 求链表长度*/ 149 | int length_list(PNODE pHead) 150 | { 151 | PNODE p = pHead->pNext; 152 | int len = 0; 153 | while (p!= NULL) { 154 | len++; 155 | p = p->pNext; 156 | } 157 | return len; 158 | } 159 | 160 | 161 | /** 链表排序*/ 162 | void sort_list(PNODE pHead) 163 | { 164 | 165 | // 数组的排序算法 <-> 链表排序互相对比更好学习排序 166 | // for (i = 0 ; i < len - 1; i++) { // 外围的排序次数 ,没执行完以此只能确定某一最大或最小值 167 | // for (j = i + 1; j < len; j++) { // 内循环的排序次数 ,执行完一次把 n 个元素,对比 n-1 次并换位置 168 | // 169 | // if ( a[i] < a[j]) { 170 | // t = a[i]; 171 | // a[i] = a[j]; 172 | // a[j] = t; 173 | // } 174 | // } 175 | // } 176 | 177 | // 排序的算法有很多种 178 | int len = length_list(pHead); 179 | int i , j , t; 180 | PNODE p , q; 181 | 182 | for (i = 0 , p = pHead->pNext; i < len - 1; i++ , p = p->pNext) { // 外围的排序次数 ,没执行完以此只能确定某一最大或最小值 183 | for (j = i + 1 , q = p->pNext; j < len; j++ , q = q->pNext) { // 内循环的排序次数 ,执行完一次把 n 个元素,对比 n-1 次并换位置 184 | 185 | if (p->data > q->data) { // 比较两个节点数值,并换位置 186 | t = p->data; 187 | p->data = q->data; 188 | q->data = t; 189 | } 190 | } 191 | } 192 | 193 | return; 194 | 195 | 196 | } 197 | 198 | 199 | /** 200 | 链表在某个位置插入某个元素 201 | @param pHead 要被插入的链表 202 | @param pos 要插入的位置 203 | @param val 要插入的值 204 | @return 返回是否插入成功 205 | */ 206 | bool insert_list(PNODE pHead , int pos , int val){ 207 | 208 | // 判断位置是否合法 209 | PNODE q = pHead; // 要插入的位置,如果是 <= 0,则直接插到最前面,如果是 pos = 1 就插入第一个后面,pos = n,就插到第 n 个后面 210 | int i = 0; 211 | while (i < pos) { 212 | if (q->pNext == NULL) { 213 | printf("要插入的位置不合法;大于链表长度\n"); 214 | break; 215 | }else{ 216 | q = q->pNext; //要被插入的节点 217 | i++; 218 | } 219 | } 220 | 221 | 222 | // 插入操作 223 | PNODE p = (PNODE)malloc(sizeof(NODE)); 224 | if (p == NULL) { 225 | printf("动态分配内存失败\n"); 226 | exit(0); 227 | } 228 | p->data = val; 229 | 230 | // 前一个节点为q, 直接添加到 q 后面。 231 | p->pNext = q->pNext; 232 | q->pNext = p; 233 | 234 | return true; 235 | } 236 | 237 | 238 | /** 239 | 链表删除某个元素 240 | 241 | 242 | 243 | @param pHead 要操作的链表 244 | @param pos 要被删除的节点的位置,当pos <= 1 则删除第一个元素,当pos > 链表长度则返回false,并报告原因 245 | @param val 被删除节点的值 246 | @return 是否成功 247 | */ 248 | bool delete_list(PNODE pHead , int pos , int * val){ 249 | 250 | // 找到要被删除的元素保存起来 251 | PNODE p = pHead; 252 | int i = 0; 253 | while (i < pos - 1) { // 找到被删除节点的前一个节点 254 | 255 | if (p->pNext == NULL) { 256 | break; 257 | } 258 | p = p->pNext; 259 | i++; 260 | } 261 | 262 | if (i < pos && p->pNext == NULL) { 263 | printf("你要删除的位置非法,此位置不在链表长度范围之内\n"); 264 | return false; 265 | } 266 | 267 | // 找到了要被删除的那个节点 268 | PNODE t = p->pNext;; 269 | *val = t->data; // 把被删除节点的值传给外面 270 | 271 | p->pNext = t->pNext; // 直接指向后面一个节点 272 | free(t); // 释放被删除节点内存,防止内存泄漏 273 | 274 | return true; 275 | } 276 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B444AEE91FE4210100365280 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B444AEE81FE4210100365280 /* main.m */; }; 11 | B4D2B8FD1FEB9F7500915C60 /* XYStack.m in Sources */ = {isa = PBXBuildFile; fileRef = B4D2B8FC1FEB9F7500915C60 /* XYStack.m */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXCopyFilesBuildPhase section */ 15 | B444AEE31FE4210100365280 /* CopyFiles */ = { 16 | isa = PBXCopyFilesBuildPhase; 17 | buildActionMask = 2147483647; 18 | dstPath = /usr/share/man/man1/; 19 | dstSubfolderSpec = 0; 20 | files = ( 21 | ); 22 | runOnlyForDeploymentPostprocessing = 1; 23 | }; 24 | /* End PBXCopyFilesBuildPhase section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | B444AEE51FE4210100365280 /* 栈 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "栈"; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | B444AEE81FE4210100365280 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 29 | B4D2B8FB1FEB9F7500915C60 /* XYStack.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XYStack.h; sourceTree = ""; }; 30 | B4D2B8FC1FEB9F7500915C60 /* XYStack.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XYStack.m; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | B444AEE21FE4210100365280 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | B444AEDC1FE4210100365280 = { 45 | isa = PBXGroup; 46 | children = ( 47 | B444AEE71FE4210100365280 /* 栈 */, 48 | B444AEE61FE4210100365280 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | B444AEE61FE4210100365280 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | B444AEE51FE4210100365280 /* 栈 */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | B444AEE71FE4210100365280 /* 栈 */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | B444AEE81FE4210100365280 /* main.m */, 64 | B4D2B8FB1FEB9F7500915C60 /* XYStack.h */, 65 | B4D2B8FC1FEB9F7500915C60 /* XYStack.m */, 66 | ); 67 | path = "栈"; 68 | sourceTree = ""; 69 | }; 70 | /* End PBXGroup section */ 71 | 72 | /* Begin PBXNativeTarget section */ 73 | B444AEE41FE4210100365280 /* 栈 */ = { 74 | isa = PBXNativeTarget; 75 | buildConfigurationList = B444AEEC1FE4210100365280 /* Build configuration list for PBXNativeTarget "栈" */; 76 | buildPhases = ( 77 | B444AEE11FE4210100365280 /* Sources */, 78 | B444AEE21FE4210100365280 /* Frameworks */, 79 | B444AEE31FE4210100365280 /* CopyFiles */, 80 | ); 81 | buildRules = ( 82 | ); 83 | dependencies = ( 84 | ); 85 | name = "栈"; 86 | productName = "栈"; 87 | productReference = B444AEE51FE4210100365280 /* 栈 */; 88 | productType = "com.apple.product-type.tool"; 89 | }; 90 | /* End PBXNativeTarget section */ 91 | 92 | /* Begin PBXProject section */ 93 | B444AEDD1FE4210100365280 /* Project object */ = { 94 | isa = PBXProject; 95 | attributes = { 96 | LastUpgradeCheck = 0910; 97 | ORGANIZATIONNAME = XiaoYou; 98 | TargetAttributes = { 99 | B444AEE41FE4210100365280 = { 100 | CreatedOnToolsVersion = 9.1; 101 | ProvisioningStyle = Automatic; 102 | }; 103 | }; 104 | }; 105 | buildConfigurationList = B444AEE01FE4210100365280 /* Build configuration list for PBXProject "栈" */; 106 | compatibilityVersion = "Xcode 8.0"; 107 | developmentRegion = en; 108 | hasScannedForEncodings = 0; 109 | knownRegions = ( 110 | en, 111 | ); 112 | mainGroup = B444AEDC1FE4210100365280; 113 | productRefGroup = B444AEE61FE4210100365280 /* Products */; 114 | projectDirPath = ""; 115 | projectRoot = ""; 116 | targets = ( 117 | B444AEE41FE4210100365280 /* 栈 */, 118 | ); 119 | }; 120 | /* End PBXProject section */ 121 | 122 | /* Begin PBXSourcesBuildPhase section */ 123 | B444AEE11FE4210100365280 /* Sources */ = { 124 | isa = PBXSourcesBuildPhase; 125 | buildActionMask = 2147483647; 126 | files = ( 127 | B4D2B8FD1FEB9F7500915C60 /* XYStack.m in Sources */, 128 | B444AEE91FE4210100365280 /* main.m in Sources */, 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXSourcesBuildPhase section */ 133 | 134 | /* Begin XCBuildConfiguration section */ 135 | B444AEEA1FE4210100365280 /* Debug */ = { 136 | isa = XCBuildConfiguration; 137 | buildSettings = { 138 | ALWAYS_SEARCH_USER_PATHS = NO; 139 | CLANG_ANALYZER_NONNULL = YES; 140 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 141 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 142 | CLANG_CXX_LIBRARY = "libc++"; 143 | CLANG_ENABLE_MODULES = YES; 144 | CLANG_ENABLE_OBJC_ARC = YES; 145 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 146 | CLANG_WARN_BOOL_CONVERSION = YES; 147 | CLANG_WARN_COMMA = YES; 148 | CLANG_WARN_CONSTANT_CONVERSION = YES; 149 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 150 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 151 | CLANG_WARN_EMPTY_BODY = YES; 152 | CLANG_WARN_ENUM_CONVERSION = YES; 153 | CLANG_WARN_INFINITE_RECURSION = YES; 154 | CLANG_WARN_INT_CONVERSION = YES; 155 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 156 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 157 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 158 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 159 | CLANG_WARN_STRICT_PROTOTYPES = YES; 160 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 161 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 162 | CLANG_WARN_UNREACHABLE_CODE = YES; 163 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 164 | CODE_SIGN_IDENTITY = "Mac Developer"; 165 | COPY_PHASE_STRIP = NO; 166 | DEBUG_INFORMATION_FORMAT = dwarf; 167 | ENABLE_STRICT_OBJC_MSGSEND = YES; 168 | ENABLE_TESTABILITY = YES; 169 | GCC_C_LANGUAGE_STANDARD = gnu11; 170 | GCC_DYNAMIC_NO_PIC = NO; 171 | GCC_NO_COMMON_BLOCKS = YES; 172 | GCC_OPTIMIZATION_LEVEL = 0; 173 | GCC_PREPROCESSOR_DEFINITIONS = ( 174 | "DEBUG=1", 175 | "$(inherited)", 176 | ); 177 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 178 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 179 | GCC_WARN_UNDECLARED_SELECTOR = YES; 180 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 181 | GCC_WARN_UNUSED_FUNCTION = YES; 182 | GCC_WARN_UNUSED_VARIABLE = YES; 183 | MACOSX_DEPLOYMENT_TARGET = 10.13; 184 | MTL_ENABLE_DEBUG_INFO = YES; 185 | ONLY_ACTIVE_ARCH = YES; 186 | SDKROOT = macosx; 187 | }; 188 | name = Debug; 189 | }; 190 | B444AEEB1FE4210100365280 /* Release */ = { 191 | isa = XCBuildConfiguration; 192 | buildSettings = { 193 | ALWAYS_SEARCH_USER_PATHS = NO; 194 | CLANG_ANALYZER_NONNULL = YES; 195 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 196 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 197 | CLANG_CXX_LIBRARY = "libc++"; 198 | CLANG_ENABLE_MODULES = YES; 199 | CLANG_ENABLE_OBJC_ARC = YES; 200 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 201 | CLANG_WARN_BOOL_CONVERSION = YES; 202 | CLANG_WARN_COMMA = YES; 203 | CLANG_WARN_CONSTANT_CONVERSION = YES; 204 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 205 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INFINITE_RECURSION = YES; 209 | CLANG_WARN_INT_CONVERSION = YES; 210 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 214 | CLANG_WARN_STRICT_PROTOTYPES = YES; 215 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 216 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 217 | CLANG_WARN_UNREACHABLE_CODE = YES; 218 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 219 | CODE_SIGN_IDENTITY = "Mac Developer"; 220 | COPY_PHASE_STRIP = NO; 221 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 222 | ENABLE_NS_ASSERTIONS = NO; 223 | ENABLE_STRICT_OBJC_MSGSEND = YES; 224 | GCC_C_LANGUAGE_STANDARD = gnu11; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 228 | GCC_WARN_UNDECLARED_SELECTOR = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 230 | GCC_WARN_UNUSED_FUNCTION = YES; 231 | GCC_WARN_UNUSED_VARIABLE = YES; 232 | MACOSX_DEPLOYMENT_TARGET = 10.13; 233 | MTL_ENABLE_DEBUG_INFO = NO; 234 | SDKROOT = macosx; 235 | }; 236 | name = Release; 237 | }; 238 | B444AEED1FE4210100365280 /* Debug */ = { 239 | isa = XCBuildConfiguration; 240 | buildSettings = { 241 | CODE_SIGN_STYLE = Automatic; 242 | DEVELOPMENT_TEAM = SLUU2646N5; 243 | PRODUCT_NAME = "$(TARGET_NAME)"; 244 | }; 245 | name = Debug; 246 | }; 247 | B444AEEE1FE4210100365280 /* Release */ = { 248 | isa = XCBuildConfiguration; 249 | buildSettings = { 250 | CODE_SIGN_STYLE = Automatic; 251 | DEVELOPMENT_TEAM = SLUU2646N5; 252 | PRODUCT_NAME = "$(TARGET_NAME)"; 253 | }; 254 | name = Release; 255 | }; 256 | /* End XCBuildConfiguration section */ 257 | 258 | /* Begin XCConfigurationList section */ 259 | B444AEE01FE4210100365280 /* Build configuration list for PBXProject "栈" */ = { 260 | isa = XCConfigurationList; 261 | buildConfigurations = ( 262 | B444AEEA1FE4210100365280 /* Debug */, 263 | B444AEEB1FE4210100365280 /* Release */, 264 | ); 265 | defaultConfigurationIsVisible = 0; 266 | defaultConfigurationName = Release; 267 | }; 268 | B444AEEC1FE4210100365280 /* Build configuration list for PBXNativeTarget "栈" */ = { 269 | isa = XCConfigurationList; 270 | buildConfigurations = ( 271 | B444AEED1FE4210100365280 /* Debug */, 272 | B444AEEE1FE4210100365280 /* Release */, 273 | ); 274 | defaultConfigurationIsVisible = 0; 275 | defaultConfigurationName = Release; 276 | }; 277 | /* End XCConfigurationList section */ 278 | }; 279 | rootObject = B444AEDD1FE4210100365280 /* Project object */; 280 | } 281 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/03.栈/栈.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 栈.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈/XYStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // XYStack.h 3 | // 栈 4 | // 5 | // Created by 渠晓友 on 2017/12/21. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface XYStack : NSObject 12 | @end 13 | 14 | 15 | #pragma mark --- 栈的定义和基本方法 16 | 17 | typedef struct Node{ // 节点 18 | 19 | int data; 20 | struct Node *pNext; 21 | 22 | }*PNODE,NODE; 23 | 24 | typedef struct Stack{ // 栈 25 | 26 | PNODE pTop; 27 | PNODE pBottom; 28 | 29 | }STACK,*PSTACK; 30 | 31 | /**栈的初始化*/ 32 | void init(PSTACK); 33 | /**压栈*/ 34 | void push(PSTACK,int); 35 | /**出栈*/ 36 | int pop(PSTACK , int *); 37 | /**遍历打印栈*/ 38 | void traverse(PSTACK); 39 | /**是否为空栈*/ 40 | int isEmpty(PSTACK); 41 | /**清空栈*/ 42 | void clearStack(PSTACK); 43 | 44 | 45 | #pragma mark --- 栈的使用 46 | 47 | /** 48 | 进位制转换 49 | */ 50 | void conversion(void); 51 | 52 | /** 53 | 检测括号 54 | */ 55 | void checkBracelet(void); 56 | 57 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈/XYStack.m: -------------------------------------------------------------------------------- 1 | // 2 | // XYStack.m 3 | // 栈 4 | // 5 | // Created by 渠晓友 on 2017/12/21. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import "XYStack.h" 10 | 11 | @implementation XYStack 12 | @end 13 | 14 | 15 | /**栈的初始化*/ 16 | void init(PSTACK pS){ 17 | 18 | pS->pTop = (PNODE)malloc(sizeof(NODE)); 19 | if (pS->pTop == NULL) { 20 | printf("内存分配失败退出"); 21 | return; 22 | }else 23 | { 24 | pS->pBottom = pS->pTop; 25 | pS->pTop->pNext = NULL; 26 | } 27 | } 28 | 29 | 30 | /**遍历打印栈*/ 31 | void traverse(PSTACK pS){ 32 | 33 | // 只要不是空栈,就一直输出 34 | // while (pS->pTop != pS->pBottom) { 35 | // printf("%d ",pS->pTop->data); 36 | // 37 | // pS->pTop = pS->pTop->pNext; // 把top的下一个节点付给top,继续遍历 38 | // } 39 | // printf("\n"); 40 | // 41 | // 为什么不用上面这个方法? 42 | // 因为直接使用 pTop 指针进行遍历的错过中,一直对它进行赋值,直接导致它改变了不在指向顶部,而是遍历完成之后最后指向底部了,所以要用一个临时指针测试一下就好。 43 | 44 | // 只要不是空栈,就一直输出 45 | PNODE p = pS->pTop; 46 | while (p != pS->pBottom) { 47 | printf("%d ",p->data); 48 | 49 | p = p->pNext; // 把top的下一个节点付给top,继续遍历 50 | } 51 | printf("\n"); 52 | } 53 | 54 | /**是否为空栈*/ 55 | int isEmpty(PSTACK pS) 56 | { 57 | if (pS->pTop == pS->pBottom) { 58 | return 1; 59 | }else 60 | { 61 | return 0; 62 | } 63 | } 64 | 65 | /** 66 | 压栈 67 | 68 | @param pS 执行压栈的栈指针 69 | @param val 被压栈的值 70 | */ 71 | void push(PSTACK pS,int val){ 72 | 73 | // 创建新节点,放到栈顶 74 | 75 | PNODE pNew = (PNODE)malloc(sizeof(NODE)); 76 | pNew->data = val; 77 | pNew->pNext = pS->pTop; 78 | 79 | pS->pTop = pNew; // 栈顶指针指向新元素 80 | } 81 | 82 | /** 83 | 出栈 84 | 85 | @param pS 执行出栈的栈地址 86 | @param val 出栈值的地址 87 | @return 是否出栈成功 88 | */ 89 | int pop(PSTACK pS , int *val){ 90 | 91 | if (isEmpty(pS)) { 92 | printf(" 空栈 ,出栈失败"); 93 | return 0; 94 | }else 95 | { 96 | PNODE p = pS->pTop; 97 | pS->pTop = p->pNext; 98 | 99 | if (val != NULL) { 100 | *val = p->data; 101 | } 102 | free(p); // 释放原来top内存 103 | p = NULL; 104 | return 1; 105 | } 106 | } 107 | 108 | /**清空栈*/ 109 | void clearStack(PSTACK pS){ 110 | 111 | if (isEmpty(pS)) { 112 | return; 113 | }else{ 114 | PNODE p = pS->pTop; 115 | PNODE q = NULL; 116 | 117 | while (p!=pS->pBottom) { 118 | q = p->pNext; 119 | free(p); 120 | p = q; 121 | } 122 | pS->pTop = pS->pBottom; 123 | } 124 | 125 | 126 | // 偷懒的做法 127 | // while (!isEmpty(pS)) { 128 | // pop(pS, NULL); 129 | // } 130 | } 131 | 132 | #pragma mark -- 栈的应用举例 133 | 134 | /** 135 | 进位制转换 136 | */ 137 | void conversion(void){ 138 | 139 | // 创建栈 140 | STACK S; 141 | init(&S); 142 | 143 | // 用户输入十进制数 144 | int N; 145 | printf("请输入非负十进制正整数:\n"); 146 | scanf("%d",&N); 147 | 148 | // 可以做一些对数字的合法性验证 149 | if (N <= 0) { 150 | return; //输入有误 151 | } 152 | 153 | // 放入栈中 154 | while (N) { 155 | push(&S, N % 8); 156 | N = N / 8; 157 | } 158 | 159 | 160 | // 打印出来 161 | printf("对应八进制数字为:"); 162 | int a; 163 | while (!isEmpty(&S)) { 164 | pop(&S, &a); 165 | printf("%d",a); 166 | } 167 | printf("\n"); 168 | 169 | return; // 程序结束 170 | } 171 | 172 | 173 | /** 174 | 检测括号(本实例用数字代替括号) 175 | 176 | [ ] --> 1 , 2 177 | ( ) --> 3 , 4 178 | 179 | */ 180 | void checkBracelet(void) 181 | { 182 | // 创建栈 183 | STACK S; 184 | init(&S); 185 | 186 | // 用户输入括号 187 | int N; 188 | printf("请输入对应的括号(end结束):\n"); 189 | scanf("%d",&N); 190 | 191 | if (isEmpty(&S)) { 192 | push(&S, N); 193 | printf("第一个括号输入\n"); 194 | traverse(&S); // 打印此时栈内容 195 | } 196 | 197 | while (!isEmpty(&S)) { 198 | 199 | // 用户输入括号 200 | int N; 201 | printf("请输入对应的括号(0结束):\n"); 202 | scanf("%d",&N); 203 | 204 | if (N == 0) { 205 | break; 206 | } 207 | 208 | // 判断当前栈顶是否符合标准, 209 | if (S.pTop->data == N) { 210 | printf("消除一对\n"); 211 | pop(&S, NULL); 212 | traverse(&S); // 打印此时栈内容 213 | }else 214 | { 215 | printf("未消除\n"); 216 | push(&S, N); 217 | traverse(&S); // 打印此时栈内容 218 | } 219 | } 220 | } 221 | 222 | 223 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/03.栈/栈/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 栈 4 | // 5 | // Created by 渠晓友 on 2017/12/15. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "XYStack.h" 11 | 12 | int main(void){ 13 | 14 | // 栈的基本使用 15 | // STACK stack; // 声明一个栈 16 | // init(&stack); // 初始化 17 | // 18 | // // 压栈 19 | // push(&stack, 10); 20 | // push(&stack, 20); 21 | // push(&stack, 30); 22 | // push(&stack, 40); 23 | // push(&stack, 50); 24 | // 25 | // traverse(&stack); // 遍历打印栈 26 | // 27 | // int val; 28 | // int isPopSuccess = pop(&stack,&val); 29 | // if (isPopSuccess) { 30 | // printf("pop 的值为 %d\n",val); 31 | // } 32 | // 33 | // traverse(&stack); 34 | // 35 | // clearStack(&stack); // 清空栈 36 | // traverse(&stack); 37 | // 38 | 39 | // 栈的应用 40 | 41 | conversion(); 42 | 43 | checkBracelet(); 44 | 45 | return 0; 46 | 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | #pragma mark -- 引入栈↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ 55 | 56 | //typedef struct Student{ 57 | // 58 | // int age; // 年龄 59 | // char *name; // 姓名 60 | // float height; // 身高 61 | // 62 | //}*pStudent,Student; 63 | // 64 | //void func(void){ 65 | // 66 | // // 变量 p 在栈区分配内存, --- (int)malloc(sizeof(int));在堆区分配了 int 类型大小的内存空间 67 | // int p = (int)malloc(sizeof(int)); 68 | // p = 10; 69 | //} 70 | // 71 | //int main(void) { 72 | // 73 | // // 声明创建局部变量 --- 栈内存 ,,, 10,“xiaoming”,1.73 这些都是系统常量区的内容 74 | // int age = 10; 75 | // char *name = "xiaoming"; 76 | // float height = 1.73; 77 | // 78 | // // 创建结构体变量 xiaoming 作为机构体变量分配在栈区 79 | // // (pStudent)malloc(sizeof(Student)); 这句代码则是在堆区动态分配内存空间创建了一个结构体变量 80 | // pStudent xiaoming = (pStudent)malloc(sizeof(Student)); 81 | // 82 | // xiaoming->age = age; 83 | // xiaoming->name = name; 84 | // xiaoming->height = height; 85 | // return 0; 86 | //} 87 | 88 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B4391F9A1FF33AA200546DD3 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B4391F991FF33AA200546DD3 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | B4391F941FF33AA200546DD3 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | B4391F961FF33AA200546DD3 /* 队列 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "队列"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B4391F991FF33AA200546DD3 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | B4391F931FF33AA200546DD3 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | B4391F8D1FF33AA200546DD3 = { 42 | isa = PBXGroup; 43 | children = ( 44 | B4391F981FF33AA200546DD3 /* 队列 */, 45 | B4391F971FF33AA200546DD3 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | B4391F971FF33AA200546DD3 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B4391F961FF33AA200546DD3 /* 队列 */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | B4391F981FF33AA200546DD3 /* 队列 */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B4391F991FF33AA200546DD3 /* main.m */, 61 | ); 62 | path = "队列"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | B4391F951FF33AA200546DD3 /* 队列 */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = B4391F9D1FF33AA200546DD3 /* Build configuration list for PBXNativeTarget "队列" */; 71 | buildPhases = ( 72 | B4391F921FF33AA200546DD3 /* Sources */, 73 | B4391F931FF33AA200546DD3 /* Frameworks */, 74 | B4391F941FF33AA200546DD3 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "队列"; 81 | productName = "队列"; 82 | productReference = B4391F961FF33AA200546DD3 /* 队列 */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | B4391F8E1FF33AA200546DD3 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0910; 92 | ORGANIZATIONNAME = XiaoYou; 93 | TargetAttributes = { 94 | B4391F951FF33AA200546DD3 = { 95 | CreatedOnToolsVersion = 9.1; 96 | ProvisioningStyle = Automatic; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = B4391F911FF33AA200546DD3 /* Build configuration list for PBXProject "队列" */; 101 | compatibilityVersion = "Xcode 8.0"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = B4391F8D1FF33AA200546DD3; 108 | productRefGroup = B4391F971FF33AA200546DD3 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | B4391F951FF33AA200546DD3 /* 队列 */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | B4391F921FF33AA200546DD3 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | B4391F9A1FF33AA200546DD3 /* main.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | B4391F9B1FF33AA200546DD3 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 144 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 145 | CLANG_WARN_EMPTY_BODY = YES; 146 | CLANG_WARN_ENUM_CONVERSION = YES; 147 | CLANG_WARN_INFINITE_RECURSION = YES; 148 | CLANG_WARN_INT_CONVERSION = YES; 149 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 150 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 152 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 153 | CLANG_WARN_STRICT_PROTOTYPES = YES; 154 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 155 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 156 | CLANG_WARN_UNREACHABLE_CODE = YES; 157 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 158 | CODE_SIGN_IDENTITY = "Mac Developer"; 159 | COPY_PHASE_STRIP = NO; 160 | DEBUG_INFORMATION_FORMAT = dwarf; 161 | ENABLE_STRICT_OBJC_MSGSEND = YES; 162 | ENABLE_TESTABILITY = YES; 163 | GCC_C_LANGUAGE_STANDARD = gnu11; 164 | GCC_DYNAMIC_NO_PIC = NO; 165 | GCC_NO_COMMON_BLOCKS = YES; 166 | GCC_OPTIMIZATION_LEVEL = 0; 167 | GCC_PREPROCESSOR_DEFINITIONS = ( 168 | "DEBUG=1", 169 | "$(inherited)", 170 | ); 171 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 172 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 173 | GCC_WARN_UNDECLARED_SELECTOR = YES; 174 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 175 | GCC_WARN_UNUSED_FUNCTION = YES; 176 | GCC_WARN_UNUSED_VARIABLE = YES; 177 | MACOSX_DEPLOYMENT_TARGET = 10.13; 178 | MTL_ENABLE_DEBUG_INFO = YES; 179 | ONLY_ACTIVE_ARCH = YES; 180 | SDKROOT = macosx; 181 | }; 182 | name = Debug; 183 | }; 184 | B4391F9C1FF33AA200546DD3 /* Release */ = { 185 | isa = XCBuildConfiguration; 186 | buildSettings = { 187 | ALWAYS_SEARCH_USER_PATHS = NO; 188 | CLANG_ANALYZER_NONNULL = YES; 189 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 190 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 191 | CLANG_CXX_LIBRARY = "libc++"; 192 | CLANG_ENABLE_MODULES = YES; 193 | CLANG_ENABLE_OBJC_ARC = YES; 194 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 195 | CLANG_WARN_BOOL_CONVERSION = YES; 196 | CLANG_WARN_COMMA = YES; 197 | CLANG_WARN_CONSTANT_CONVERSION = YES; 198 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 199 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 200 | CLANG_WARN_EMPTY_BODY = YES; 201 | CLANG_WARN_ENUM_CONVERSION = YES; 202 | CLANG_WARN_INFINITE_RECURSION = YES; 203 | CLANG_WARN_INT_CONVERSION = YES; 204 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 205 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 206 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 207 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 208 | CLANG_WARN_STRICT_PROTOTYPES = YES; 209 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 210 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 211 | CLANG_WARN_UNREACHABLE_CODE = YES; 212 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 213 | CODE_SIGN_IDENTITY = "Mac Developer"; 214 | COPY_PHASE_STRIP = NO; 215 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 216 | ENABLE_NS_ASSERTIONS = NO; 217 | ENABLE_STRICT_OBJC_MSGSEND = YES; 218 | GCC_C_LANGUAGE_STANDARD = gnu11; 219 | GCC_NO_COMMON_BLOCKS = YES; 220 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 221 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 222 | GCC_WARN_UNDECLARED_SELECTOR = YES; 223 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 224 | GCC_WARN_UNUSED_FUNCTION = YES; 225 | GCC_WARN_UNUSED_VARIABLE = YES; 226 | MACOSX_DEPLOYMENT_TARGET = 10.13; 227 | MTL_ENABLE_DEBUG_INFO = NO; 228 | SDKROOT = macosx; 229 | }; 230 | name = Release; 231 | }; 232 | B4391F9E1FF33AA200546DD3 /* Debug */ = { 233 | isa = XCBuildConfiguration; 234 | buildSettings = { 235 | CODE_SIGN_STYLE = Automatic; 236 | DEVELOPMENT_TEAM = SLUU2646N5; 237 | PRODUCT_NAME = "$(TARGET_NAME)"; 238 | }; 239 | name = Debug; 240 | }; 241 | B4391F9F1FF33AA200546DD3 /* Release */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | CODE_SIGN_STYLE = Automatic; 245 | DEVELOPMENT_TEAM = SLUU2646N5; 246 | PRODUCT_NAME = "$(TARGET_NAME)"; 247 | }; 248 | name = Release; 249 | }; 250 | /* End XCBuildConfiguration section */ 251 | 252 | /* Begin XCConfigurationList section */ 253 | B4391F911FF33AA200546DD3 /* Build configuration list for PBXProject "队列" */ = { 254 | isa = XCConfigurationList; 255 | buildConfigurations = ( 256 | B4391F9B1FF33AA200546DD3 /* Debug */, 257 | B4391F9C1FF33AA200546DD3 /* Release */, 258 | ); 259 | defaultConfigurationIsVisible = 0; 260 | defaultConfigurationName = Release; 261 | }; 262 | B4391F9D1FF33AA200546DD3 /* Build configuration list for PBXNativeTarget "队列" */ = { 263 | isa = XCConfigurationList; 264 | buildConfigurations = ( 265 | B4391F9E1FF33AA200546DD3 /* Debug */, 266 | B4391F9F1FF33AA200546DD3 /* Release */, 267 | ); 268 | defaultConfigurationIsVisible = 0; 269 | defaultConfigurationName = Release; 270 | }; 271 | /* End XCConfigurationList section */ 272 | }; 273 | rootObject = B4391F8E1FF33AA200546DD3 /* Project object */; 274 | } 275 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/04.队列/队列.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 队列.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 队列.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/04.队列/队列/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 队列 4 | // 5 | // Created by 渠晓友 on 2017/12/27. 6 | // Copyright © 2017年 XiaoYou. All rights reserved. 7 | // 8 | // 静态队列 -- 假设最大长度为 6 9 | 10 | #import 11 | 12 | 13 | #define kQueueMaxLength 6 // 假设最大长度为 6 14 | 15 | typedef struct Queue{ 16 | int * pBase; // 队列中操作的数组 17 | int front; // 队头 18 | int rear; // 对尾 19 | }QUEUE; 20 | 21 | 22 | 23 | /** 24 | 初始化队列 25 | @param pQueue 要被初始化队列地址 26 | */ 27 | void init_queue(QUEUE *pQueue); 28 | 29 | 30 | /** 31 | 入队 32 | 33 | @param pQueue 要入队的队列地址 34 | @param val 入队元素的值 35 | @return 入队成功/失败 36 | */ 37 | bool en_queue(QUEUE *pQueue , int val); 38 | 39 | /** 40 | 出队 41 | 42 | @param pQueue 要出队队列地址 43 | @param val 被出队元素地址 44 | @return 出队成功/失败 45 | */ 46 | bool de_queue(QUEUE *pQueue , int *val); 47 | 48 | /** 49 | 遍历队列 50 | 51 | @param pQueue 要遍历的队列的地址 52 | */ 53 | void tranverce_queue(QUEUE *pQueue); 54 | 55 | 56 | /** 57 | 判断队列是否已满 58 | 59 | @param pQueue 被判断队列 60 | @return 是否已满 61 | */ 62 | bool full_queue(QUEUE *pQueue); 63 | 64 | /** 65 | 判断队列是否为空 66 | 67 | @param pQueue 被判断队列 68 | @return 是否为空 69 | */ 70 | bool empty_queue(QUEUE *pQueue); 71 | 72 | 73 | 74 | int main() { 75 | 76 | 77 | QUEUE q; // 声明队列q 78 | init_queue(&q); // 初始化队列q 79 | 80 | en_queue(&q, 2); // 插入元素 81 | en_queue(&q, 21); // 插入元素 82 | en_queue(&q, 3); // 插入元素 83 | en_queue(&q, 4); // 插入元素 84 | en_queue(&q, 5); // 插入元素 85 | en_queue(&q, 6); // 插入元素 86 | en_queue(&q, 7); // 插入元素 87 | en_queue(&q, 8); // 插入元素 88 | 89 | tranverce_queue(&q); //遍历队列 90 | 91 | int i; 92 | bool b; 93 | b = de_queue(&q, &i); // 出队 94 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 95 | 96 | b = de_queue(&q, &i); // 出队 97 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 98 | 99 | b = de_queue(&q, &i); // 出队 100 | printf("出队%s,元素为 %d\n",b?"成功":"失败",i); 101 | 102 | tranverce_queue(&q); //遍历队列 103 | 104 | return 0; 105 | } 106 | 107 | void init_queue(QUEUE *pQueue){ 108 | 109 | pQueue->pBase = (int *)malloc(sizeof(int) * kQueueMaxLength); // 初始化,pBase指向长度6的 int* 数组 110 | pQueue->front = pQueue->rear = 0; 111 | 112 | } 113 | 114 | bool full_queue(QUEUE *pQueue){ 115 | 116 | // 判断是否已满,用第二种方式:少用数组中一个元素,f 和 r 的关系为 f == (r + 1) % maxLenght 117 | if ((pQueue->rear + 1) % kQueueMaxLength == pQueue->front){ 118 | return true; 119 | }else 120 | { 121 | return false; 122 | } 123 | 124 | } 125 | 126 | bool empty_queue(QUEUE *pQueue){ 127 | 128 | // 队列为空即: f = r 129 | 130 | if (pQueue->front == pQueue->rear) { 131 | return true; 132 | }else 133 | { 134 | return false; 135 | } 136 | } 137 | 138 | bool en_queue(QUEUE *pQueue , int val){ 139 | 140 | if (full_queue(pQueue)) { // 队列已满,直接返回入队失败 141 | return false; 142 | }else 143 | { // 队列未满,执行入队操作 144 | 145 | // 1.元素插入数组中 146 | pQueue->pBase[pQueue->rear] = val; 147 | // 2.队头队尾的表示 148 | pQueue->rear = (pQueue->rear + 1) % kQueueMaxLength; 149 | 150 | return true; 151 | } 152 | } 153 | 154 | bool de_queue(QUEUE *pQueue , int *val){ 155 | 156 | if (empty_queue(pQueue)) { // 如果是空队列,直接出队失败 157 | return false; 158 | }else 159 | { 160 | // 出队->保存被出队元素的值 161 | *val = pQueue->pBase[pQueue->front]; 162 | // 修改队头位置 163 | pQueue->front = (pQueue->front + 1) % kQueueMaxLength; 164 | 165 | } 166 | return true; 167 | } 168 | 169 | void tranverce_queue(QUEUE *pQueue){ 170 | 171 | int i = pQueue->front; 172 | int lenght = 0; 173 | while (i != pQueue->rear) { 174 | lenght ++; 175 | i = (i + 1) % kQueueMaxLength; 176 | } 177 | printf("队列中共有 %d 个元素\n",lenght); 178 | 179 | i = pQueue->front; 180 | while (i != pQueue->rear) { 181 | 182 | printf("第 %d 个元素为 %d\n",i + 1,pQueue->pBase[i]); 183 | i = (i + 1) % kQueueMaxLength; 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | B444977923092FA50082E89C /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B444977823092FA50082E89C /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | B444977323092FA50082E89C /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | B444977523092FA50082E89C /* 递归 */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "递归"; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | B444977823092FA50082E89C /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | B444977223092FA50082E89C /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | B444976C23092FA50082E89C = { 42 | isa = PBXGroup; 43 | children = ( 44 | B444977723092FA50082E89C /* 递归 */, 45 | B444977623092FA50082E89C /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | B444977623092FA50082E89C /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | B444977523092FA50082E89C /* 递归 */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | B444977723092FA50082E89C /* 递归 */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | B444977823092FA50082E89C /* main.m */, 61 | ); 62 | path = "递归"; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | B444977423092FA50082E89C /* 递归 */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = B444977C23092FA50082E89C /* Build configuration list for PBXNativeTarget "递归" */; 71 | buildPhases = ( 72 | B444977123092FA50082E89C /* Sources */, 73 | B444977223092FA50082E89C /* Frameworks */, 74 | B444977323092FA50082E89C /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = "递归"; 81 | productName = "递归"; 82 | productReference = B444977523092FA50082E89C /* 递归 */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | B444976D23092FA50082E89C /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 1020; 92 | ORGANIZATIONNAME = "渠晓友"; 93 | TargetAttributes = { 94 | B444977423092FA50082E89C = { 95 | CreatedOnToolsVersion = 10.2.1; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = B444977023092FA50082E89C /* Build configuration list for PBXProject "递归" */; 100 | compatibilityVersion = "Xcode 9.3"; 101 | developmentRegion = en; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = B444976C23092FA50082E89C; 107 | productRefGroup = B444977623092FA50082E89C /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | B444977423092FA50082E89C /* 递归 */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | B444977123092FA50082E89C /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | B444977923092FA50082E89C /* main.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | B444977A23092FA50082E89C /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_ANALYZER_NONNULL = YES; 133 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 134 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 135 | CLANG_CXX_LIBRARY = "libc++"; 136 | CLANG_ENABLE_MODULES = YES; 137 | CLANG_ENABLE_OBJC_ARC = YES; 138 | CLANG_ENABLE_OBJC_WEAK = YES; 139 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 140 | CLANG_WARN_BOOL_CONVERSION = YES; 141 | CLANG_WARN_COMMA = YES; 142 | CLANG_WARN_CONSTANT_CONVERSION = YES; 143 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 144 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 145 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 146 | CLANG_WARN_EMPTY_BODY = YES; 147 | CLANG_WARN_ENUM_CONVERSION = YES; 148 | CLANG_WARN_INFINITE_RECURSION = YES; 149 | CLANG_WARN_INT_CONVERSION = YES; 150 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 151 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 152 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 153 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 154 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 155 | CLANG_WARN_STRICT_PROTOTYPES = YES; 156 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 157 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 158 | CLANG_WARN_UNREACHABLE_CODE = YES; 159 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 160 | CODE_SIGN_IDENTITY = "Mac Developer"; 161 | COPY_PHASE_STRIP = NO; 162 | DEBUG_INFORMATION_FORMAT = dwarf; 163 | ENABLE_STRICT_OBJC_MSGSEND = YES; 164 | ENABLE_TESTABILITY = YES; 165 | GCC_C_LANGUAGE_STANDARD = gnu11; 166 | GCC_DYNAMIC_NO_PIC = NO; 167 | GCC_NO_COMMON_BLOCKS = YES; 168 | GCC_OPTIMIZATION_LEVEL = 0; 169 | GCC_PREPROCESSOR_DEFINITIONS = ( 170 | "DEBUG=1", 171 | "$(inherited)", 172 | ); 173 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 174 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 175 | GCC_WARN_UNDECLARED_SELECTOR = YES; 176 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 177 | GCC_WARN_UNUSED_FUNCTION = YES; 178 | GCC_WARN_UNUSED_VARIABLE = YES; 179 | MACOSX_DEPLOYMENT_TARGET = 10.14; 180 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 181 | MTL_FAST_MATH = YES; 182 | ONLY_ACTIVE_ARCH = YES; 183 | SDKROOT = macosx; 184 | }; 185 | name = Debug; 186 | }; 187 | B444977B23092FA50082E89C /* Release */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_ANALYZER_NONNULL = YES; 192 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 193 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 194 | CLANG_CXX_LIBRARY = "libc++"; 195 | CLANG_ENABLE_MODULES = YES; 196 | CLANG_ENABLE_OBJC_ARC = YES; 197 | CLANG_ENABLE_OBJC_WEAK = YES; 198 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 199 | CLANG_WARN_BOOL_CONVERSION = YES; 200 | CLANG_WARN_COMMA = YES; 201 | CLANG_WARN_CONSTANT_CONVERSION = YES; 202 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 203 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 204 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 205 | CLANG_WARN_EMPTY_BODY = YES; 206 | CLANG_WARN_ENUM_CONVERSION = YES; 207 | CLANG_WARN_INFINITE_RECURSION = YES; 208 | CLANG_WARN_INT_CONVERSION = YES; 209 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 210 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 211 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 212 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 213 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 214 | CLANG_WARN_STRICT_PROTOTYPES = YES; 215 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 216 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 217 | CLANG_WARN_UNREACHABLE_CODE = YES; 218 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 219 | CODE_SIGN_IDENTITY = "Mac Developer"; 220 | COPY_PHASE_STRIP = NO; 221 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 222 | ENABLE_NS_ASSERTIONS = NO; 223 | ENABLE_STRICT_OBJC_MSGSEND = YES; 224 | GCC_C_LANGUAGE_STANDARD = gnu11; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 227 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 228 | GCC_WARN_UNDECLARED_SELECTOR = YES; 229 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 230 | GCC_WARN_UNUSED_FUNCTION = YES; 231 | GCC_WARN_UNUSED_VARIABLE = YES; 232 | MACOSX_DEPLOYMENT_TARGET = 10.14; 233 | MTL_ENABLE_DEBUG_INFO = NO; 234 | MTL_FAST_MATH = YES; 235 | SDKROOT = macosx; 236 | }; 237 | name = Release; 238 | }; 239 | B444977D23092FA50082E89C /* Debug */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | CODE_SIGN_STYLE = Automatic; 243 | DEVELOPMENT_TEAM = H76H9B7E2M; 244 | PRODUCT_NAME = "$(TARGET_NAME)"; 245 | }; 246 | name = Debug; 247 | }; 248 | B444977E23092FA50082E89C /* Release */ = { 249 | isa = XCBuildConfiguration; 250 | buildSettings = { 251 | CODE_SIGN_STYLE = Automatic; 252 | DEVELOPMENT_TEAM = H76H9B7E2M; 253 | PRODUCT_NAME = "$(TARGET_NAME)"; 254 | }; 255 | name = Release; 256 | }; 257 | /* End XCBuildConfiguration section */ 258 | 259 | /* Begin XCConfigurationList section */ 260 | B444977023092FA50082E89C /* Build configuration list for PBXProject "递归" */ = { 261 | isa = XCConfigurationList; 262 | buildConfigurations = ( 263 | B444977A23092FA50082E89C /* Debug */, 264 | B444977B23092FA50082E89C /* Release */, 265 | ); 266 | defaultConfigurationIsVisible = 0; 267 | defaultConfigurationName = Release; 268 | }; 269 | B444977C23092FA50082E89C /* Build configuration list for PBXNativeTarget "递归" */ = { 270 | isa = XCConfigurationList; 271 | buildConfigurations = ( 272 | B444977D23092FA50082E89C /* Debug */, 273 | B444977E23092FA50082E89C /* Release */, 274 | ); 275 | defaultConfigurationIsVisible = 0; 276 | defaultConfigurationName = Release; 277 | }; 278 | /* End XCConfigurationList section */ 279 | }; 280 | rootObject = B444976D23092FA50082E89C /* Project object */; 281 | } 282 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaoyouPrince/DataStructure/03955af1eb9186d8c10256c0e0f0893d6f3c963c/数据结构/数据结构源码/05.递归/递归.xcodeproj/project.xcworkspace/xcuserdata/quxiaoyou.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归.xcodeproj/xcuserdata/quxiaoyou.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | 递归.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /数据结构/数据结构源码/05.递归/递归/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // 递归 4 | // 5 | // Created by 渠晓友 on 2019/8/18. 6 | // Copyright © 2019 渠晓友. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | #pragma mark - 函数相互调用 13 | 14 | void a(void); 15 | void b(void); 16 | void c(void); 17 | 18 | 19 | void a(){ 20 | printf("aaaa\n"); 21 | b(); 22 | printf("1111\n"); 23 | } 24 | 25 | void b(){ 26 | printf("bbbb\n"); 27 | c(); 28 | printf("2222\n"); 29 | } 30 | 31 | void c(){ 32 | printf("cccc\n"); 33 | // a(); 34 | printf("3333\n"); 35 | } 36 | 37 | #pragma mark - 函数自己调用自己 38 | 39 | void func(int num); 40 | 41 | void func(int num){ 42 | if (num == 1){ 43 | printf("执行目标代码\n"); 44 | } 45 | else 46 | { 47 | printf("递归自己\n"); 48 | func(num - 1); 49 | } 50 | } 51 | 52 | #pragma 递归实例 阶乘 求和 53 | 54 | /// 求一个数字的阶乘 55 | unsigned long getFactorial(int num){ 56 | 57 | 58 | // 0 验证入参为大于0的整数 59 | if (num<1) { 60 | return 0; 61 | } 62 | 63 | 64 | unsigned long result = num; 65 | 66 | // 1. for 循环求解 67 | // for( int i = num-1; i >= 1; i--){ 68 | // result = i * result; 69 | // } 70 | 71 | // 2. 递归求解 72 | if (num == 1) { 73 | return 1; 74 | }else 75 | { 76 | return result * getFactorial(num-1); 77 | } 78 | 79 | return result; 80 | 81 | } 82 | 83 | /// 求一个数字的累加和 84 | unsigned long getSum(int num){ 85 | 86 | 87 | // 0 验证入参为大于0的整数 88 | if (num<1) { 89 | return 0; 90 | } 91 | 92 | 93 | unsigned long result = num; 94 | 95 | // 1. for 循环求解 96 | for( int i = num-1; i >= 1; i--){ 97 | result = i + result; 98 | } 99 | 100 | // 2. 递归求解 101 | // if (num == 1) { 102 | // return 1; 103 | // }else 104 | // { 105 | // return result + getSum(num-1); 106 | // } 107 | 108 | return result; 109 | 110 | } 111 | 112 | 113 | /** 114 | 汉诺塔问题 115 | 116 | @param n 需要移动几个盘子 117 | @param A 柱子A,最初盘子所在的柱子 118 | @param B 柱子B,中间缓冲区的柱子 119 | @param C 柱子C,最终要将盘子移到的柱子 120 | */ 121 | void hannuota(unsigned int n, char A, char B, char C){ 122 | 123 | if( n == 1){ 124 | printf("将编号为 %d 的盘子直接从 %c 移动到 %c\n",n,A,C); 125 | }else 126 | { 127 | /* 128 | 1. 将前(n-1)个盘子,通过C移动到B 129 | 2. 将最后一个盘子从A移动到C 130 | 3. 最后将B上面的(n-1)个盘子通过A移动到C 131 | */ 132 | 133 | hannuota(n-1, A, C, B); 134 | printf("将编号为 %d 的盘子直接从 %c 移动到 %c\n",n,A,C); 135 | hannuota(n-1, B, A, C); 136 | 137 | } 138 | 139 | } 140 | 141 | 142 | int main() { 143 | 144 | hannuota(3, 'A', 'B', 'C'); 145 | 146 | 147 | return EXIT_SUCCESS; 148 | } 149 | --------------------------------------------------------------------------------