指针

超详细的函数指针

∥☆過路亽.° 提交于 2020-02-20 07:05:35
函数指针基础 使用函数指针一般要实现: 1)获取函数地址 2)声明函数指针 3)使用函数指针调用函数 ( 1 )获取函数地址 : 直接使用函数名(函数名就是地址),比如调用think()函数: show_array ( think ) ; ( 2 )声明函数指针 int sum ( int n ) ; //(1式) int ( * p ) ( int n ) ; //(2式) p = sum ; 2 式中 ( * p ) 必须加括号, ( * p ) 相当于 1 式中的sum,那么p就是指向sum ; 否则,p函数返回的是一个指针。 ( 3 )调用函数 接着( 2 )中的示例: int x = sum ( 2 ) ; int x = ( * p ) ( 2 ) ; //这两句话是一样的! 深入探讨函数指针 int arr [ 3 ] = { 6 , 2 , 1 } ; //三个函数声明(返回类型和参数形式都是一样的): const int * f1 ( const int arr [ ] , int n ) ; const int * f2 ( const int * arr , int n ) ; const int * f3 ( const int arr [ ] , int n ) ; const int * f1 ( const int arr [ ] , int n )

线索二叉树

萝らか妹 提交于 2020-02-20 05:50:19
1.产生背景 现有一棵结点数目为n的二叉树,采用二叉链表的形式存储。对于每个结点均有指向左右孩子的两个指针域,而结点为n的二叉树一共有n-1条有效分支路径。那么,则二叉链表中存在2n-(n-1)=n+1个空指针域。那么,这些空指针造成了空间浪费。 例如:图1所示一棵二叉树一共有10个结点,空指针^有11个。 此外,当对二叉树进行中序遍历时可以得到二叉树的中序序列。例如:图2.1所示二叉树的中序遍历结果为HDIBJEAFCG,可以得知A的前驱结点为E,后继结点为F。但是,这种关系的获得是建立在完成遍历后得到的,那么可不可以在建立二叉树时就记录下前驱后继的关系呢,那么在后续寻找前驱结点和后继结点时将大大提升效率。 2.线索化 现将某结点的空指针域指向该结点的前驱后继,定义规则如下: 若结点的左子树为空,则该结点的左孩子指针指向其前驱结点。 若结点的右子树为空,则该结点的右孩子指针指向其后继结点 这种指向前驱和后继的指针称为线索。将一棵普通二叉树以某种次序遍历,并添加线索的过程称为线索化。 按照规则将图1所示二叉树线索化后如图2所示 图中黑色点画线为指向后继的线索,紫色虚线为指向前驱的线索。 可以看出通过线索化,既解决了空间浪费问题,又解决了前驱后继的记录问题。 3.线索化带来新问题 经过上一节讲解后,可以将一棵二叉树线索化为一棵线索二叉树,那么新的问题产生了

C++——this指针

谁都会走 提交于 2020-02-20 03:09:17
参考链接: https://blog.csdn.net/ChaoFeiLi/article/details/103612849 https://blog.csdn.net/chenyt01/article/details/51316022 定义:指向当前对象的this指针 this指针:指向当前对象,保存当前对象的地址 类型:类名 * 类成员函数的形参列表中的第一个参数(隐含的参数) int Box::volume(){ return this->length * this->width * this->height; } C++编译器处理为: int Box::volume(Box *this){ return this->length * this->width * this->height; } 先有对象,然后有this指针 编译器的调用过程:box.volume(&box) , this = &box,然后才是成员变量或函数成员 this指针比较特殊的使用方式: 返回当前对象的地址和返回当前的对象 //类声明文件 Box* getAddr();//返回当前对象的地址 Box getSelf();//返回当前对象 //类实现文件 Box* Box::getAddr()//返回当前对象的地址 { return this; } Box Box::getSelf()//返回当前对象

delphi 函数指针

半城伤御伤魂 提交于 2020-02-19 17:36:52
Pascal 中的过程类型与C语言中的函数指针相似 ,为了统一说法,以下称函数指针。函数指针的声明只需要参数列表;如果是函数,再加个返回值。下面讲解指向非对象(一般的)函数/过程的函数指针。 例如声明一个过程类型,该类型带一个通过引用传递的整型参数: type IntProc = procedure (var Num: Integer); // IntProc是指向过程的函数指针 这个过程类型与任何参数完全相同的例程兼容,即用它声明的变量,可以指向任何此类函数,并通过其进行函数的调用。 下面是一个兼容例程: procedure DoubleTheValue (var Value: Integer); begin Value := Value * 2; end; 函数指针能用于两种不同的目的:声明函数指针类型的变量;或者把函数指针作为参数传递给另一例程。利用上面给定的类型和过程声明,你可以写出下面的代码: var IP: IntProc; X: Integer; begin IP := DoubleTheValue; X := 5; IP (X); end; 虽然这种调用方法比直接调用麻烦了,那么我们为什么要用这种方式呢? (1)因为在某些情况下,调用什么样的函数需要在实际中(运行时)决定,你可以根据条件来判断,实现用同一个表达,调用不同的函数,很是灵活. (2

C++语言里const_cast 在可变与不可变类型之间转换一、常量指针被转化成非常量指针,并且仍然指向原来的对象;

可紊 提交于 2020-02-19 13:45:21
在C语言里强制类型转换的方法非常简单,只要在要转换的变量前用括号确定要转换的类型即可,如要将一个double型的变量强制转换为int类型,代码如下: double x = 3.14; int y = (int)x; 另外,还可有更高级的转换,如把int *类型的变量转换为int ,代码如下: int x = 20; int *p = &x; int y = (int)p; 在C++语言里为了让强制类型转换更明显,更安全,所以把不同情况下的强制类型转换分为四种,分别为: static_cast 静态类型转换,属于最安全的强制类型转换。 const_cast 在可变与不可变类型之间转换 dynamic_cast 在多态的情况下,父子类之间的转换 reinterpret_cast 所有类型间的转换,最不安全的转换 1. C++中的 static_cast 执行非多态的转换,用于代替C中通常的转换操作。因此,被做为隐式类型转换使用。比如:   int i;   float f = 166.7f;   i = static_cast <int>(f);   此时结果,i的值为166。 2. C++中的 reinterpret_cast 主要是将数据从一种类型的转换为另一种类型。所谓“通常为操作数的位模式提供较低层的重新解释”也就是说将数据以二进制存在形式的重新解释。比如:   int i;

B树和B+树的插入、删除图文详解

有些话、适合烂在心里 提交于 2020-02-19 10:54:58
简介:本文主要介绍了B树和B+树的插入、删除操作。写这篇博客的目的是发现没有相关博客以举例的方式详细介绍B+树的相关操作,由于自身对某些细节也感到很迷惑,通过查阅相关资料,对B+树的操作有所顿悟,写下这篇博客以做记录。由于是自身对B+树的理解,肯定有考虑不周的情况,或者理解错误的地方,请留言指出。 1. B树 1. B树的定义 B树也称B-树,它是一颗多路平衡查找树。我们描述一颗B树时需要指定它的阶数,阶数表示了一个结点最多有多少个孩子结点,一般用字母m表示阶数。当m取2时,就是我们常见的二叉搜索树。 一颗m阶的B树定义如下: 1)每个结点最多有m-1个关键字。 2)根结点最少可以只有1个关键字。 3)非根结点至少有Math.ceil(m/2)-1个关键字。 4)每个结点中的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的所有关键字都大于它。 5)所有叶子结点都位于同一层,或者说根结点到每个叶子结点的长度都相同。 上图是一颗阶数为4的B树。在实际应用中的B树的阶数m都非常大(通常大于100),所以即使存储大量的数据,B树的高度仍然比较小。每个结点中存储了关键字(key)和关键字对应的数据(data),以及孩子结点的指针。 我们将一个key和其对应的data称为一个记录 。 但为了方便描述,除非特别说明,后续文中就用key来代替(key,

单向环形链表 约瑟夫问题

孤者浪人 提交于 2020-02-19 09:08:56
Josephu 问题为:设编号为1,2,… n的n个人围坐一圈,约定编号为k(1<=k<=n)的人从1开始报数,数到m 的那个人出列,它的下一位又从1开始报数,数到m的那个人又出列,依次类推,直到所有人出列为止,由此产生一个出队编号的序列。 链表如下图 数2下 自己也要数 所以只会移动1次 构建链表,遍历链表 分析图 first.next = 2 3.next = first 让最后一个元素的next指向first 首先 创建一个环形链表 // 创建一个first节点,当前没有编号 private Boy first = null; // 添加小孩节点,构建成一个环形的链表 public void addBoy(int nums) { // nums 做一个数据校验 if (nums < 1) { System.out.println("nums的值不正确"); return; } Boy curBoy = null; // 辅助指针,帮助构建环形链表 // 使用for来创建我们的环形链表 for (int i = 1; i <= nums; i++) { // 根据编号,创建小孩节点 Boy boy = new Boy(i); // 如果是第一个小孩 第一次 if (i == 1) { first = boy; //这是头指针 把第一个的赋值给first //不太理解

【Lintcode】415. Valid Palindrome

你。 提交于 2020-02-19 07:13:18
题目地址: https://www.lintcode.com/problem/valid-palindrome/description 给定一个字符串,只考虑字母和数字,字母忽略大小写区别,忽略所有其他字符,问该字符串是否回文。直接对撞双指针,左指针持续右移直到遇到字母或数字,右指针持续左移直到遇到字母或数字,如果指到的两个字符忽略大小写后不等,就直接返回false。循环结束后返回true。 public class Solution { /** * @param s: A string * @return: Whether the string is a valid palindrome */ public boolean isPalindrome ( String s ) { // write your code here // 判空 if ( s == null || s . isEmpty ( ) ) { return true ; } // 开两个变量做左右指针 int i = 0 , j = s . length ( ) - 1 ; while ( i < j ) { // 注意循环的时候一定要保持左右指针没有交错过去 while ( i < j && ! Character . isLetterOrDigit ( s . charAt ( i ) ) ) { i ++

归并排序指针版及链表版

ε祈祈猫儿з 提交于 2020-02-19 05:40:22
什么是归并排序    归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。   归并排序比较占用内存,但却是一种 效率高且稳定 的算法。其时间复杂度为 O(n log n) ,空间复杂度为 T(n)。其速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。   个人觉得一般归并排序用于链表的排序有奇效! 思路   归并排序的主要思想是 分治 。   主要过程是: 1.将n个元素从中间切开,分成两部分。(左边可能比右边多1个数) 2.将步骤1分成的两部分,再分别进行递归分解。直到所有部分的元素个数都为1。 3.从最底层开始逐步合并两个排好序的数列为一个有序的数列。 图片取自https://www.cnblog.com/chengxiao/p/6194356.html 指针版: # include <stdio.h> # include <string.h> # include <stdlib.h> void sort ( int x , int y , int * st ) ; //将数组分开 void Link ( int x

LeetCode刷题-- 双指针

被刻印的时光 ゝ 提交于 2020-02-19 04:27:09
26. 删除数组中的新元素 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。 示例 1: 给定数组 nums = [1,1,2], 函数应该返回新的长度 2, 并且原数组 nums 的前两个元素被修改为 1, 2。 示例 2: 给定 nums = [0,0,1,1,1,2,2,3,3,4], 函数应该返回新的长度 5, 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4。 class Solution { public int removeDuplicates ( int [ ] nums ) { //i指向要保留的数; //j遍历整个数组 int i = 0 ; for ( int j = 1 ; j < nums . length ; j ++ ) { if ( nums [ i ] != nums [ j ] ) { i ++ ; //找到了需要保留的数字,让i后移,腾出位置 nums [ i ] = nums [ j ] ; } } return i + 1 ; } } 633. 平方数之和 给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c。 示例1: 输入: 5 输出: