指针数组

数据结构与算法分析:(三)链表(上)

让人想犯罪 __ 提交于 2020-02-24 13:54:32
一、什么是链表? 链表是一种物理上 非连续 、 非顺序 的存储结构,数据元素之间的顺序是通过每个元素的 指针 (类似C语言中的指针,Java中是引用)关联的。 链表由一系列节点组成,每个节点一般至少会包含两部分信息:一部分是元素数据本身,另一部分是指向下一个元素地址的“指针”。这样的存储结构让链表相比其他线性的数据结构来说,操作会复杂一些。 说到链表,我们经常拿来与数组比。我们先看下面一张图再来对比它们的各自的优劣。 从图中我们看到,数组需要一块 连续 的内存空间来存储,对内存的要求比较高。如果我们申请一个 100MB 大小的数组,当内存中没有连续的、足够大的存储空间时,即便内存的剩余总可用空间大于 100MB,仍然会申请失败。 而链表恰恰相反,它并不需要一块连续的内存空间,它通过“指针”将一组零散的内存块串联起来使用,所以如果我们申请的是 100MB 大小的链表,根本不会有问题。 这里先思考一下下面这个问题。 Q:数组在实现上为什么使用的是连续的内存空间? A:可以借助 CPU 的缓存机制,预读数组中的数据,所以访问效率更高。而链表在内存中并不是连续存储,所以对 CPU 缓存不友好,没办法有效预读。 Q:上一答案中CPU缓存机制指的是什么?为什么就数组更好了? A: CPU在从内存读取数据的时候,会先把读取到的数据加载到CPU的缓存中

关于数组和指针作为参数时遇到的问题

≡放荡痞女 提交于 2020-02-23 19:09:04
自己在实现一个类strcpy函数时,发现一些小问题: 首先,函数如下: char *str_n_cpy(char *dest,const char *src) { char *_temp = dest; assert(dest != NULL || src !=NULL); //注意越界 printf("%d",sizeof(dest)); while((*dest++ = *src++) != '\0'); return _temp;}   main函数如下: int main() { char *str1 = "123"; char *str2 = "4567"; printf("%s\n",str_n_cpy(str1,3,str2,3)); return 0; }   运行程序会发现程序崩溃,后来在main函数中把char *str1 = "123"改成char str1[3]={"123"};会发现程序就能正常运行,为什么会这样呢? 经查知,前者实际将str1指向一个常量”123“了,即此时的str1是一个常量指针,其中的内容固然不可改变,所以赋值操作不能进行了;而后者str1实际作为一个普通的char型指针传到函数中,自然可以进行赋值操作。 来源: https://www.cnblogs.com/wangkundentisy/p/4202027.html

C++内存管理转自http://soft.yesky.com/lesson/110/2381610.shtml

拈花ヽ惹草 提交于 2020-02-23 15:04:50
转自 http://soft.yesky.com/lesson/110/2381610.shtml 踏入C++中的雷区——C++内存管理详解 2006-04-25 09:22 作者:蒋涛 出处:计算机教学网 责任编辑:方舟   伟大的Bill Gates 曾经失言:   640K ought to be enough for everybody — Bill Gates 1981   程序员们经常编写内存管理程序,往往提心吊胆。如果不想触雷,唯一的解决办法就是发现所有潜伏的地雷并且排除它们,躲是躲不了的。本文的内容比一般教科书的要深入得多,读者需细心阅读,做到真正地通晓内存管理。    1、内存分配方式   内存分配方式有三种:   (1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static变量。   (2)在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。   (3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。    2

删除排序数组中的重复项

时光怂恿深爱的人放手 提交于 2020-02-22 16:31:30
删除排序数组中的重复项——c++实现 题目描述 对于数组问题首要想到指针,本题采用双指针。 将第一个指针指向数组中第一个元素,第二个指针指向数组中第二个元素,第二个指针从前往后遍历,若第一个指针与第二个指针所指元素不相同,将第一个指针向后移一位。最终返回值为第一个指针所指的元素个数加一,算法如下: 来源: CSDN 作者: weixin_45773701 链接: https://blog.csdn.net/weixin_45773701/article/details/104443070

c语言进阶6-指针

我与影子孤独终老i 提交于 2020-02-22 02:43:27
指针是c语言的一个重要组成部分 是c语言的核心、精髓所在,用好指针可以在c语言编程中起到事半功倍的效果。一方面,可以提高程序的编译效率和执行速度以及实现动态的存储分配;另一方面,使用指针可使程序更灵活,全球表示各种数据结构,编写高质量的程序。 指针是c语言显著的优点之一,其使用起来十分灵活而且能提高某些程序的效率,但是如果使用不当则很容易造成系统错误。许多程序“挂死“往往都是由于错误地使用指针造成的 一、 地址与指针 系统的内存就好比是带有编号的小房间,如果想使用内存就需要得到房间编号。图1定义了一个整型变量i,整型变量需要4个字节,所以编译器为变量i分配的编号为1000~1003. 什么是地址? 地址就是内存区中对每个字节的编号 ,如图1所示的1000/1001/1002和1003就是地址,为了进一步说明来看图2. 内存地址 内容 1000 0 变量i 1004 1 变量j 1008 2 1012 3 1016 4 1020 5 图2所示的1000、1004等就是内存单元的地址,而0、1就是内存单元的内容,换种说法就是基本整型变量i在内存中的地址从1000开始。因为基本整型占4个字节,所以变量j在内存中的起始地址为1004,变量i的内容是0. 那么指针又是什么呢?这里仅将 指针看作是内存中的一个地址,多数情况下,这个地址就是内存中另一个变量的位置,如图3所示。

栈与队列

旧巷老猫 提交于 2020-02-21 19:37:30
目录 1 栈的定义 2 栈的顺序存储结构及实现 2.1 栈的顺序存储结构 2.2 栈的顺序存储结构--进栈出栈操作 3 两栈共享空间 4 栈的链式存储结构及实现 4.1 栈的链式存储结构--进栈操作 4.2 栈的链式存储结构--出栈操作 5 栈的应用--四则运算表达式求值 5.1 后缀表达式计算结果 5.2 中缀表达式转后缀表达式 6 队列的定义 7 循环队列 7.1 队列顺序存储 7.2 循环队列定义 8 队列的链式存储结构及实现 8.1 队列的链式存储结构--入队操作 8.2 队列的链式存储结构--出队操作 1 栈的定义 栈是限定仅在表尾进行插入和删除操作的线性表。允许插入和删除的一端称为栈顶,另一端称为栈底,不含任何数据元素的栈称为空栈,栈又称为后进先出(Last In First Out)的线性表,简称LIFO结构。 栈是一个线性表,栈元素具有线性关系,即前驱后继关系,栈的表尾是指栈顶,而不是栈底。栈底是固定的,最先进栈的只能在栈底,栈的插入操作,叫作进栈,栈的删除操作,叫作出栈。 2 栈的顺序存储结构及实现 2.1 栈的顺序存储结构 栈的顺序存储其实也是线性表存储的简化,称为顺序栈;线性表是用数组来实现的,下标为0的一端作为栈底比较好,因为首元素都存在栈底,变化最小,所以让它作栈底。 定义一个top变量指示栈顶元素在数组中的位置,若存储栈的长度为StackSize

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 输出:

2020/2/18-C语言复习-字符串与指针

无人久伴 提交于 2020-02-18 21:27:03
C语言复习-字符串与指针 例一: 【字符串处理 去除C代码中的注释】      C/C++代码中有两种注释,/* */和//。编译器编译预处理时会先移除注释。就是把/*和*/之间的部分去掉,把//以及之后的部分删掉。这里约定,如果出现了/* AAAA /* BBBB */的情况,也就是/**/中出现了/*,那么第二个/*是不当作注释起始的。编写函数void removeComment(char *str)。    分析:对于字符串”int c=4,/*c累计量*/ a=3;/*变量*/ // a初值为3 ”先用 strstr函数 在str中确认”/*” 是否出现过,是则再确认”*/” 是否出现过,是则 把str中自”*/”出现位置后2个字符起始的字符串复制到str中”/*”开始的位置,覆盖掉注释部分。 循环查找直到找不到”/*”为止;再用strstr在str中确认”//” 是否出现过,是则 把出现”//”的位置上置为’\0’ 。 #include <stdio.h> #include <string.h> void removeComment(char *str) { char *p=str, *q; while ((p=strstr(p, "/*")) != NULL) { q=strstr(p, "*/"); if (q != NULL) strcpy(p, q+2); } p

双指针总结

流过昼夜 提交于 2020-02-18 14:51:08
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 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。 你不需要考虑数组中超出新长度后面的元素。 我们使用i,j两个二指针, j 在前面走。如果 j 指向的元素等于 i 指向的元素 j 直接向前移,如果 j 指向的元素不等于 i 指向的元素,i 向前移 ,将 j 指向的元素赋给 i ,j向前移 public int removeDuplicates(int[] nums) { int i=0; for(int j=1;j<nums.length;++j){ if(nums[j] != nums[i]){ if(j-i != 1){ nums[++i]=nums[j]; } else{ ++i; //i,j相邻 直接 ++i } } } return i+1; } 给定一个已按照升序排列

【C语言】- 指向一维数组元素的指针!学习不需要带口罩,只要带脑子

 ̄綄美尐妖づ 提交于 2020-02-17 22:47:46
前面我们已经学习了指针,如果指针存储了某个变量的地址,我们就可以说指针指向这个变量。数组及其数组元素都占有存储空间,都有自己的地址,因此指针变量可以指向整个数组,也可以指向数组元素。 一、用指针指向一维数组的元素 输出结果: 说明已经通过指针间接修改了数组元素的值,跟指向一个普通int类型变量是一样的。 由于数组名代表着数组的首地址,即a == &a[0],因此第8行代码等价于: // 让指针指向数组的第0个元素 p = a; 内存分析图如下,一个指针变量占用2个字节,一个int类型的数组元素占用2个字节 二、用指针遍历数组元素 1.最普通的遍历方式是用数组下标来遍历元素 输出结果: 2.接下来我们用指针来遍历数组元素 先定义一个指针,指向数组的第一个元素 p的值是a[0]的地址,因此,现在我们利用指针p只能访问数组的第0个元素a[0],用*p就可取出a[0]的值1。要想访问其他元素,就必须拿到元素的地址,可以发现每个元素的地址差值为2,因为在16位编译器环境下,一个int类型的变量占用2个字节。现在只是知道a[0]的地址值为p,怎么根据a[0]的地址获取其他元素的地址呢?其实非常简单,p+1就是a[1]的地址。注意了,这里的p+1代表着p的值加2,并不是p的值加1,比如p的值为ffc3,p+1则为ffc5,而非ffc4。依次类推,p+2就是a[2]的地址ffc7,p+3就是a[3