数据结构与算法
数据结构与算法实现以及原理剖析
刘小小小小刘
https://liuziqiao.github.io/
展开
-
BitMap算法基本操作
上篇我们讲了BitMap是如何对数据进行存储的,没看过的可以看一下 BitMap算法介绍这篇我们来讲一下BitMap这个数据结构的代码实现。回顾下数据的存储原理一个二进制位对应一个非负数n,如果n存在,则对应的二进制位的值为1,否则为0。这个时候,我们的第一个问题:我们在使用byte,int,short,long等这些数据类型在存储数据的时候,他们最小的都要占用一个字节的内存,...原创 2018-11-06 16:49:08 · 509 阅读 · 0 评论 -
BitMap算法介绍
问题引出我们先来看个简单的问题。假如给你20亿个非负数的int型整数,然后再给你一个非负数的int型整数 t ,让你判断t是否存在于这20亿数中,你会怎么做呢?有人可能会用一个int数组,然后把20亿个数给存进去,然后再循环遍历一下就可以了。想一下,这样的话,时间复杂度是O(n),所需要的内存空间4byte * 20亿,一共需要80亿个字节,大概需要8GB的内存空间,显然有...原创 2018-11-03 23:48:50 · 1247 阅读 · 0 评论 -
冒泡排序
冒泡排序(Bubble Sort)冒泡排序是一种极其简单的排序算法,也是我所学的第一个排序算法。它重复地走访过要排序的元素,依次比较相邻两个元素,如果他们的顺序错误就把他们调换过来,直到没有元素再需要交换,排序完成。这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢“浮”到数列的顶端。冒泡排序算法的运作如下: 比较相邻的元素,如果前一个比后一个大,就把它们两个调换位置。 ...原创 2018-08-01 19:21:34 · 271 阅读 · 0 评论 -
二分查找(折半查找)
二分查找又称折半查找,它是一种效率较高的查找方法。 二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构。不妨设有序表是递增有序的。 二分查找的基本思想是: 设R[low..high]是当前的查找区间 (1)首先确定该区间的中点位置: (2)然后将待查的K值与R[mid].key比较:...原创 2018-07-29 08:28:47 · 673 阅读 · 0 评论 -
选择排序法
选择法排序:每次选择所要排序的数组中的最大值(由小到大排序则选择最小值)的数组元素,将这个数组元素的值与最前面没有进行排序的数组元素的值互换。以数字9、6、15、4、2为例,采用选择法实现数字按从小到大进行排序,每次交换的顺序如图所示。从图可以发现,在第一次排序过程中将第一个数字和最小的数字进行了位置互换;而第二次排序过程中,将第二个数字和剩下的数字中最小的数字进行了位置互换;依此类推,每...原创 2018-07-23 19:28:59 · 2552 阅读 · 0 评论 -
模拟实现qsort函数
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>int my_cmp(const void* p1,const void* p2){ return *(int*)p1 - *(int*)p2;}void my_swap(void* p1,void* p2,int size){ int i = 0; for (...原创 2018-06-20 23:06:24 · 347 阅读 · 0 评论 -
队列实现栈
利用两个队列实现一个栈要求:Push:往非空队列里插入(如果两个队列都是空,选第一个插入)Pop:从非空队列中 move size - 1 个元素到 空队列中,pop 剩下的一个Top: 从非空队列中 move size - 1 个元素到 空队列中,返回剩下的一个的值, 把剩下的一个也放入另一个队列中实现部分结构体定义以下代码基于队列的基本操作Queue.h,关于Queu...原创 2018-10-14 20:57:32 · 163 阅读 · 0 评论 -
栈实现队列
结构体定义首先我们需要引入栈文件Stack.h#include "Stack.h"/**两个栈实现一个队列*/typedef struct Queues{ Stack stack1; Stack stack2;}Queues;初始化void QueuesInit(Queues *pQs){ StackInit(&(pQs->stack1));...原创 2018-10-14 20:56:41 · 91 阅读 · 0 评论 -
链表面试题
关于链表已经学了有一段时间了,今天抽空进行了整理,列出来常见的有关链表的面试题,以下想法如有瑕疵望批评指出,希望能给初学者带来一点参考和价值从尾到头打印单链表递归打印// 1、从尾到头打印单链表 递归void ListReversePrint(ListNode *Node){ if (Node == NULL) { return; } ListReversePrin...原创 2018-10-05 14:03:55 · 142 阅读 · 0 评论 -
链表的基本操作
学习链表有段时间了,今天给大家整理了有关链表的基本操作,例如链表的创建、增、删、查等基本操作结构体定义typedef int DataType;typedef struct ListNode{ DataType data; struct ListNode *next;} ListNode;头文件的定义其中包含了面试题的头文件void ListInit(List...原创 2018-10-05 14:03:18 · 328 阅读 · 0 评论 -
七大排序
排序分为内部排序和外部排序,内部排序是数据记录在内存中进行排序,而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。 我们这里的八大排序就是内部排序。快速排序:是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;冒泡排序基本思想:在要排序的一组数中,对当前还未排好序的范围内的全部数,自上而下对相邻的两个...原创 2018-09-15 22:45:23 · 180 阅读 · 0 评论 -
哈希表(下)
哈希冲突的开散列方式在我的博客哈希表上中详细介绍了哈希的概念以及处理哈希冲突的闭散列方式。在本文章中,主要介绍处理哈希冲突的另一种方式:开散列(链地址)。开散列的概念开散列:又叫链地址法、开链法。首先对关键码集合用哈希函数计算哈希地址,具有相同哈希地址的关键码归于同一子集合中,每一个子集合称为一个桶,各个桶中的元素通过一个单链表的方式链接起来(可以头插的方式将桶中元素链接起来),链表的...原创 2018-09-14 18:11:15 · 110 阅读 · 0 评论 -
哈希表(上)
哈希冲突的闭散列处理方式哈希的概念在顺序搜索以及二叉树搜索树中,元素存储的位置与元素的关键码之间没有对应的关系,因此查找一个元素时,必须要经过关键码的多次比较,搜索效率取决于搜索过程中元素的比较次数。理想的搜索方法是:可以不经过任何的比较,一次直接从中找到要搜索的元素。如果构造一种存储结构,通过某种函数使得元素的存储位置与元素的关键码之间有一一映射的关系,那么在查找过程中通过该哈希函数可...原创 2018-09-08 22:41:26 · 219 阅读 · 0 评论 -
二叉搜索树
二叉搜索树概念二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树若它的左子树不为空,则左子树上所有节点的值都小于根节点的值 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树二叉搜索树操作头文件定义typedef int DataType;typedef struct BSTreeNode{ DataTyp...原创 2018-08-31 22:48:16 · 144 阅读 · 0 评论 -
二叉堆
堆的概念 如果有一个关键码的集合K = {k0,k1, k2,…,kn-1},把它的所有元 素按完全二叉树的顺序存储方式存储在一个一维数组中,并满足: Ki <= K2i+1 且 Ki<= K2i+2 (Ki >= K2i+1 且 Ki >= K2i+2) i = 0,1,2…,则称为小堆(或大堆)。 小堆(大堆)中:任一结点的关键码均小于(大于)等于它的左...原创 2018-08-28 22:42:33 · 119 阅读 · 0 评论 -
二叉树基本操作下
二叉树进阶将三种递归遍历改写成非递归遍历形式头文件引用#pragma once/*二叉树的遍历非递归、层序遍历、是否是完全二叉树*/#include "BTree.h" #include "Stack.h" //递归遍历用stack完成#include "Queue.h" //层序遍历用queue完成先序遍历void preOrderTraverse(...原创 2018-08-26 23:57:48 · 163 阅读 · 0 评论 -
二叉树基本操作上
二叉树的概念一棵二叉树是结点的一个有限集合,该集合或者为空,或者是由一个根节点加上两棵分别称为左子树和右子树的二叉树组成二叉树特点:每个结点最多有两棵子树,即二叉树不存在度大于2的结点 二叉树的子树有左右之分,其子树的次序不能颠倒因此:二叉树是通过上述形式的组合或嵌套而形成满二叉树&完全二叉树满二叉树:在一棵二叉树中,如果所有分支结点都存在左子树和右子树,并且所有叶子节...原创 2018-08-25 22:01:18 · 365 阅读 · 0 评论 -
复杂链表的复制
复制链表的复制在复杂链表中,每个结点除了有一个next指针指向下一个结点之外,还有一个random指向链表中的任意结点或者NULL。结点定义如下typedef struct Link_C{ int data; struct Link_C *next; struct Link_C *random;}Link_C;思路:(我们分三步骤)第一步:复制结点...原创 2018-08-24 08:48:29 · 163 阅读 · 0 评论 -
判断元素入栈出栈的合法性
判断元素入栈出栈的合法性一般来说,这种判断性的问题会出现在一些面试题目的选择题中,当然学习了栈之后,我们就要有解决这种问题的能力。思路: 判断元素是否相同,相同就进行下一个元素比较,当栈不为空并且栈顶元素和输出的栈元素相同,则将该元素出栈并指向输出元素的下一个,否则就将该元素进栈,并指向比较的元素的下一个 ,直到所有元素比较完然后按出栈顺序进行比较,当栈不为空时,将栈顶元素与当前元素进行比较...原创 2018-08-23 17:24:19 · 541 阅读 · 0 评论 -
栈实现括号匹配
栈实现括号匹配匹配思想:从左至右扫描一个字符串(或表达式),则每个右括号将与最近遇到的那个左括号相匹配。则可以在从左至右扫描过程中把所遇到的左括号存放到堆栈中。每当遇到一个右括号时,就将它与栈顶的左括号(如果存在)相匹配,同时从栈顶删除该左括号。算法思想:设置一个栈,当读到左括号时,左括号进栈。当读到右括号时,则从栈中弹出一个元素,与读到的左括号进行匹配,若匹配成功,继续读入;否则匹配失败,返...原创 2018-08-23 08:35:13 · 12935 阅读 · 0 评论