数据结构和算法
数据结构
算法
Dannii_
一名苦逼加班的 做游戏的 后台开发的 程序猿 =_=
展开
-
Trie树 字典树 前缀树
字典树通过共享字符串的公共前缀来达到节省空间的目的。比如 “abc” 和 “ab” 和 “d”,构建的字典树如下表示,红色表示一个串的结束。比如我们做一个26个字母的字典树每个节点下都有26种可能的分支。因此定义每个节点的结构TrieNode如下:#include <iostream>#include <stdlib.h>#include <stdio.h>#include <memory.h>#include <mche原创 2020-08-29 17:04:46 · 315 阅读 · 0 评论 -
堆排序
预处理器是在编译之前执行的一段程序,可以部分地改变我们所写的程序。 预处理器可以确保头文件多次包含但仍能安全工作。头文件保护符 #define:指令把一个名字设定为预处理器变量。 #ifdef:当且仅当变量已定义时为真 #ifndef:当且仅当变量未定义时为真 一旦检查结果为真,则执行后续操作直至遇到#endif指令为止原创 2020-06-20 17:02:55 · 176 阅读 · 0 评论 -
二叉堆的构建、插入、删除等操作
共享内存就是两个或者多个进程共享的一块区域。只要一个进程改变了这块地址中的内容的时候,其他进程便会察觉到改变的内容。(1)创建共享内存 int shmget(key_t key, int size, int shmflg) (2)将共享内存映射到自己的内存空间 void* shmat(int shmid, const void* shmaddr, int shmflg) shmi...原创 2020-06-20 15:51:59 · 2246 阅读 · 0 评论 -
选择排序
选择排序是一种灵巧的算法,但其速度不是很快。具体规则如下:1:从未排序元素中找到最小(大)元素,存放到排序序列的起始位置。(我们以最小值举例)2:再从剩余的未排序元素中继续寻找最小元素,然后放到已排序序列的末尾(通过交换元素值实现,如果最小元素比第一个未排序元素小,那就交换他们的值)3:重复第二步,直到所有元素排序完成时间复杂度:O(n^2)要遍历n次,即针对每个元素,对他们进行排...原创 2020-04-24 11:30:10 · 231 阅读 · 0 评论 -
调整数组顺序使奇数位于偶数前面
剑指Offer面试题13题目: 给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。分析: 时间复杂度为O(n)的方法:(通过 i 结点的前一个结点) 删除节点i之前,先从链表的头结点开始遍历到i前面的一个结点h,把h的next指向i的下一个结点。再删除结点i时间复杂度为O(1)的方法:(通过 i 结点的后一个结点) 我们可以很方便的找到 i 结点原创 2017-01-30 20:52:58 · 280 阅读 · 0 评论 -
二叉搜索树的后序遍历序列
剑指Offer面试题24题目: 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。分析: 后序遍历的序列中:左子树 + 右子树 +根节点 并且: 左子树的值 < 根节点 < 右子树的值 所以数组中最后一位是根节点,前半部分小于根节点为左子树,后半部分大于根节点为右子树class Solution {pu原创 2017-01-30 21:57:01 · 193 阅读 · 0 评论 -
复杂链表的复制
剑指Offer面试题26题目: 输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针 random指向任意一个节点或者NULL),返回结果为复制后复杂链表的head。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)分析: 再不用辅助空间的情况下实现O(n)的时间效率。 1、根据原始链表的每个结点N创建对应的N’,把N’链接在N的后面 v原创 2017-01-31 23:13:20 · 221 阅读 · 0 评论 -
插入排序
插入排序的基本思想: 在一个已排好序的记录子集的基础上,每一步将下一个待排序的记录有序插入已经排好序的记录子集中,直到将所有待排记录全部插入为止。直接插入排序:是最简单的插入排序方法 插入排序的基本方法是: 每步将一个待排序的记录按其关键字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止。直接插入排序(straight insertion sort)的做法是: 1、每次从无原创 2017-02-01 16:39:40 · 398 阅读 · 0 评论 -
插入排序----折半插入排序算法
1、在将一个新元素插入已排好序的数组的过程中,寻找插入点时,将待插入区域(已排好序的区域)的首元素设置为a[low],末元素设置为a[high],则比较时将待插入元素与a[m], 2、其中m=(low+high)/2相比较,如果比参考元素小,则选择a[low]到a[m-1]为新的插入区域(即high=m-1), 3、否则选择a[m+1]到a[high]为新的插入区域(即low=m+1), 4、原创 2017-02-01 22:42:38 · 810 阅读 · 0 评论 -
插入排序----希尔排序算法
希尔排序又称缩小增量排序法。首先,将待排序的关键字序列分成若干个较小的子序列,对子序列进行直接插入排序,使整个待排序序列排好序。希尔排序是基于插入排序的以下两点性质而提出改进方法的: 1、插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率。 2、插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。希尔排序的过程: 在希尔排序中,各子序列的排序过程是相对独立的,具原创 2017-02-01 22:56:58 · 473 阅读 · 0 评论 -
翻转单词顺序
剑指Offer面试题42题目: 输入一个英文句子,翻转句子中单词的顺序,但单词内字符的顺序不变。为简单起见,标点符号和普通字符一样处理。例如输入字符串”I am a student.”,则输出”student. a am I”。思路一:把英文句子倒着输出可以把单词看做一个整体的进栈出栈情况处理。 通过扫描空格来确定每个单词的起始和终止位置。class Solution {public:原创 2017-02-02 22:51:13 · 779 阅读 · 0 评论 -
实现GetMin功能的栈
【题目】 实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小元素的栈。【要求】 1、pop、push、getMin操作的时间复杂度都为O(1) 2、设计的站类型可以使用现成的栈结构栈的一些基本定义模板://头文件#include <stack>//模板<类型名> template <t...原创 2016-11-19 13:38:18 · 555 阅读 · 0 评论 -
double类型值相等判断
两实数相等:两实数的差在允许的范围内认为相等既可认为是相等的。范围:1e-6(0.000001)主要代码:int IsEqual(double a,double b){ return fabs(a-b) < 0.000001;}整个判断代码#include <iostream>#include <cmath>using namespace std;int IsEqual(double原创 2017-01-16 19:34:50 · 9678 阅读 · 0 评论 -
打印1到最大的n位数
剑指Offer面试题12题目: 输入数字n,按顺序打印出从1到最大的n位十进制数,比如输入3,则打印出1、2、3直到最大的3位数即999。分析: 错误思路: 先计算出n位数的最大值。然后用一个循环从1开始逐个打印。 缺陷: 这个题目没有规定n的范围,当输入的n很大的时候,我们求最大的n位数是不是用整型(int)或者长整型(long long)都会溢出?也就是说我们要考虑大数的问题。void原创 2017-01-29 21:26:17 · 199 阅读 · 0 评论 -
数值的整数次方
剑指Offer面试题11题目: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。不得使用库函数,同时不需要考虑大数问题。分析: 考虑不够全面的错误思路: 由于不考虑大数的问题,有一种简单的思路直接相乘。 但是这个没有考虑到指数是0或者指数小于1的情况,只考虑了指数是正数的情况。double Power(double base,in原创 2017-01-28 19:50:57 · 196 阅读 · 0 评论 -
Int to Roman And Roman to Int
罗马数字:罗马数字有下面七个基本符号:I(1)、V(5)、X(10)、L(50)、C(100)、D(500)、 M(1000)用罗马数字表示数时:如果几个相同的数字并列、就表示这个数的值是数码的几倍。 例如:罗马数字要表示 3,可以写成 Ⅲ;要表示20,可以写成 XX;不相同的几个数码并列时,如果小的数码在右边,就表示数的数值是这几个数码的和。例如:6 用罗马数字可以表示为 Ⅵ;如果小的数码在原创 2017-01-25 22:49:04 · 203 阅读 · 0 评论 -
从尾到头打印链表
LeetCode第三题:从尾到头打印链表LeetCode给的最初代码:/*** struct ListNode {* int val;* struct ListNode *next;* ListNode(int x) :* val(x), next(NULL) {* }* };*/class So原创 2017-01-14 14:15:07 · 407 阅读 · 0 评论 -
反转链表
剑指offer面试题16题目描述 输入一个链表,反转链表后,输出链表的所有元素。分析: 头结点存储数据。已知链表: pReverseHead为最终反转后的链表头指针: 注意要给pReverseHead->next设置为NULL,否则pReverseHead后面等于pHead所含结点 改变指针指向的具体操作: 第一次改变指针指向后: /*struct ListNode { in原创 2017-01-18 23:26:25 · 190 阅读 · 0 评论 -
顺时针打印矩阵
剑指offer面试题20题目: 输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下矩阵: 1 2 3 4 5 6 7 8 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.分析: 要求从外圈到内圈的顺序来打印矩阵,我们可以原创 2017-01-18 14:58:20 · 209 阅读 · 0 评论 -
树的子结构
题目: 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)分析: 1、在树A中找到和B的根节点的值一样的结点R 2、判断树A中以R为根节点的子树是不是包含和树B一样的结构二叉树遍历:一般采用递归的方法/*struct TreeNode { int val; struct TreeNode *left; struct TreeNo原创 2017-01-19 11:04:31 · 196 阅读 · 0 评论 -
二叉树的镜像
题目: 操作给定的二叉树,将其变换为源二叉树的镜像。 二叉树的镜像定义: 源二叉树 : 8 / \ 6 10 / \ / \ 5 7 9 11 镜像二叉树: 8 / \ 10 6原创 2017-01-19 11:33:28 · 218 阅读 · 0 评论 -
从上往下打印二叉树
剑指offer面试题题目描述 从上往下打印出二叉树的每个节点,同层节点从左至右打印。分析 1、题目是考察二叉树的遍历 2、按层次遍历 3、从根结点开始打印 3、把根节点的左右子节点存储下来,才能接着遍历左右字节的子节点。 4、还要依次把根节点的左右字节点取出来遍历其子节点 5、由此,我们可以想到要用队列来存储结点,满足先入先出由此我们找到规律: 1、每一次打印一个结点的时候,如果该结原创 2017-01-19 14:03:52 · 309 阅读 · 0 评论 -
二叉树的深度
剑指Offer面试题39题题目: 输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。分析: 1、若二叉树只有根节点,则深度为1 2、若二叉树只有左子树,则深度为 左子树的深度 + 1 3、若二叉树只有右子树,则深度为 右子树的深度 + 1 4、若即有左子树又有右子树,则二叉树的深度为左、右子树深度的较大值 + 1显然可以原创 2017-01-22 17:34:36 · 296 阅读 · 0 评论 -
二分查找算法(折半查找算法)
二分查找又称折半查找。 优点:比较次数少,查找速度快,平均性能好; 缺点:要求待查表为有序表,且插入删除困难。折半查找方法适用于不经常变动而查找频繁的有序列表。 1、首先,假设表中元素是按升序排列 2、将表中间位置记录的关键字与查找关键字比较 3、如果两者相等,则查找成功; 4、否则利用中间位置记录将表分成前、后两个子表, 5、如果中间位置记录的关键字大于查找关键字,则进一步查找前一子原创 2017-01-22 19:51:40 · 462 阅读 · 0 评论 -
归并排序算法求逆序对数
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列(即先使每个子序列有序,再使子序列段间有序)。 若将两个有序表合并成一个有序表,称为二路归并。归并过程为: 1、比较a[i]和a[j]的大小, 2、若a[i]≤a[j],则将第一个有序表中的元素a[i]复原创 2017-01-23 23:50:38 · 1068 阅读 · 0 评论 -
二进制中1的个数
题目: 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。错误方法1:(移动整数的二进制,遇到负数的情况会陷入死循环) 1、先判断整数二进制表示中最右边一位是不是1 2、把输入的整数右移一位,此时原来处于从右边起的第二位被移动到最右边了,再判断是不是1 3、这样依次移动一位,知道整数整数变成0为止 判断最右边是不是1:把整数和1做一次位运算。若结果是1,说明整数最右边是1,否原创 2017-01-24 11:30:13 · 289 阅读 · 0 评论 -
斐波那契数列
剑指Offer面试题9题目: 斐波那契数列(Fibonacci sequence)又称黄金分割数列,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34… 写一个函数,输入一个整数n,请你输出斐波那契数列的第n项。法一:递归。但是有严重的效率问题。 例如要求f(10),首先要求得f(9)和f(8), 要求得f(9),需要首先求得f(8)和f(7) 要求得f(8),需要首先求得f原创 2017-01-24 11:41:32 · 287 阅读 · 0 评论 -
递归可能出现的性能问题
递归算法的代码很简洁。但同时也存在缺点。递归由于函数要调用自身,而函数调用是有时间和空间的消耗的。每一次函数调用,都需要在内存栈中分配空间以保存参数、返回地址及临时变量,而且往栈里压入数据和弹出数据都需要时间。递归有可能很多计算都是重复的,从而对性能带来很大的负面影响。递归的本质是把一个问题分解成两个或者多个小问题。如果小问题有重叠的部分,那么就存在重复的计算。除了效率外,递归还可能存在调用栈原创 2017-01-24 13:13:12 · 6483 阅读 · 0 评论 -
单链表的创建(有头结点和无头结点)
1、有头结点的单链表的创建#include <iostream>using namespace std;struct ListNode{ int val; ListNode *next; };//有头结点的单链表的创建 int CreateListNode(ListNode *head){ if(head == NULL) return 123;原创 2017-01-14 13:37:26 · 15199 阅读 · 6 评论