数据结构笔记1(c++)_指针
一、数据结构概述
1.定义:
我们如何把现实中大量而复杂的问题,以特定的数据类型和特定的存储结构保存到主存储器(内存)中,以及在此基础上为实现某个功能(比如查找某个元素,删除某个元素,对所有元素进行排序)而执行的相应操作。这个相应的操作也叫算法。
数据结构 =个体的存储 + 个体的关系存储
算法(狭义) = 对存储数据的操作
2.算法:解题的方法和步骤
2.1.衡量算法好坏的标准:
2.1.1.时间复杂度:程序大概执行的次数,而非执行的时间
2.1.2.空间复杂度:算法执行过程中大概所占用的最大内存
2.1.3.难易程度(编算法最重要的)
2.1.4.健壮性
3.数据结构的地位:数据结构是软件中最核心的课程
程序 = 数据的存储 + 数据的操作 + 可以被计算机执行的语言
二、预备知识
1.指针
1.1.指针的重要性:指针是c语言的灵魂
1.2.有关指针概念的定义:
指针就是地址 地址就是指针,指针和地址是一个概念
指针变量 是存放内存单元地址的变量,所谓内存单元地址 即为内存单元编号,两者是一个概念
指针的本质 是一个操作受限的非负整数/从0开始的非负整数
范围:0 -- FFFFFFFF【4G-1】
1.2.1.关于内存和cpu的关系:
CPU能够直接访问的只有内存,内存是CPU唯一能够访问的大容量储存器,内存的基本划分单位是字节,每个字节有8位,每一位存放1个0或1个1,CPU和内存打交道的方式:地址线、控制线、数据线
内存可以看做很多小格子,如果是32位,编号从0到4G-1;
1.2.1.1.地址线 可以确定对哪一个单元编号进行操作,地址没有编号,地址就是编号;重点是地址线,因为地址线是32位的,所以最大只能0到32-1;内存的编号不能重复,但是内容可以重复;
定义:地址就是内存单元的编号,单元编号是死的,不能改变,但是里面的内容是可以改变的;当一个程序运行完成,内存会被回收(回收和销毁不是一个概念,操作系统会分配内存给程序,程序告诉操作系统,操作系统会把内存中的空间释放出来,原始的数据(遗留的垃圾数字)不会销毁,只是不能使用而已(c存在这个问题,但是java不会,java会自动释放),其中的变量会被清空,但是内存、单元编号依然存在;
1.2.1.2.控制线 用来确定是:读、写、只读、只写;
1.2.1.3.数据线 可以进行数据传输
2.指针的分类:
2.1.基本类型的指针
2.1.1基本概念
#include <stdio.h> int main(void)
{
int * p; //该p变量只能存储int类型的地址,不能存放一个整数
int i = ;
int j; // char ch = 'A';
// p = &ch; //p只能存放int类型,不能存放char类型的'A',类型不一致,会报错
// p = 10; //error p是个变量名字,表示只能存放int型变量地址,10是个整数,不是个地址;
// *p = i; //可以存放i,一定要如下理解才可以
// 1)将i的地址发送给p,意味着p是指向i的;
// 2)修改p、i的值,不会影响另外一个值,相互不会影响;
// 3)*p即为i变量本身,i跟*p可以在任何地方进行互换,i的值改了,*p的值也改了,i原来等于100,*p也就等于100,但是p不是i,i不是p;
p = &i; // 如果这一行被省略掉,会报错;
// 第一步int * p;只是说p可以保存整型变量地址了,但p中并没有保存真正的整型变量地址,所以我们不知道*p真正指向的是谁了
// 虽然p中没有保存真正有效整型数字地址,但是p中还是可以有垃圾数字的,垃圾数字也有可能是某一个变量的地址,所以*p最终指向的是一个不确定的单元,*p不知道指向了哪里,造成了混乱,c语言中不允许这样去写
// 不能将一个不确定单元的值,赋给另外一个变量,这样不合适,所以会报错
*p = i; // 等价于i=i,不会出错,但是没有什么实际意义
j = *p; // 等价于j = i; 若注释掉这一行,则j没有赋值,c会自动赋予一个垃圾数字-2341343;
printf("i = %d, j= %d, *p = %d\n",i, j, *p); //printf();
return ;
}
小结:
1、如果一个指针变量(假定为p)存放了某个普通变量,那我们就可以说:“p指向了i”,但p与i是两个变量;修改p的值不影响i的值,修改i的值不影响p的值
2、*p等价于I 或者说*p可以与i在任何地方互换
3、如果一个指针变量指向了某个普通变量,则*指针变量就完全等价于该普通变量
注意:
指针变量也是变量,只不过它存放的不能是内存单元的内容,只能存放内存单元的地址
普通变量前不能加*
常量和表达式前不能加&
如何通过被调函数,修改主调函数中普通变量的值
1.实参为相关变量的地址:&i
2.形参为以该变量的类型为类型的指针变量:*p
3.在被调用函数中通过*形参变量名的方式修改主函数:*p=100
2.2.指针和数组的关系(一维数组)
//Array_point_1.cpp
# include <stdio.h> int main(void)
{
int a[] = {,,,,}; // 1)a中存放的不是1~5这5个数字,这5个数字是在a0到a4中存放的。
// 2)数组名a存放的是数组的第一个元素的地址
// 3)它的值不能被改变
// 4)字母a即为一维数组名,指向的是数组的第一个元素,即a指向的是a0
// 5)a[3]和*(a+3)的关系:a[i] <<==>> *(a+i) 即数组a[i]的写法,等价于*(a+i) a[3] == *(3+a), 3[a] == *(a+3), 因a指向第一个元素a[0],故a+3指向第四个元素a[3],则*(a+3)==a[3];
// 理论上指针比下标的速度快,但是可以忽略不计
//a[3] == *(3+a); printf("%p\n", a+);
printf("%p\n", a+);
printf("%p\n", a+); //[Out]:
//0019FF30
//0019FF34
//0019FF38 printf("%d\n", *a+); // *a+3等价于 a[0]+3 = 4
//[Out]:
//
return ;
}
2.2.1.数组名:a[*]中的a
一维数组名 是个指针常量,它存放的是一维数组第一个元素的地址a[0],它的值不能被改变
一维数组名指向的是 数组的第一个元素
2.2.2.下标和指针的关系:a[i]等价于*(a+i)
a[i] <<==>> *(a+i)
假设指针变量的名字为p,则p+i的值是p+i*(p所指向的变量所占的字节数)
2.2.3.指针变量的运算:
指针变量不能相加,不能相乘, 不能相除,如果两指针变量属于同一数组,则可以相减
指针变量可以加减一整数,前提是最终结果不能超过指针
p+i 的值是p+i*(p所指向的变量所占的字节数)
p- i 的值是p-i*(p所指向的变量所占的字节数)
p++ <==> p+1 // 如果是int型,就是4字节,double型,就是8字节,但是都是指向的后一个元素
p-- <==> p-1
2.2.4.举例:
如何通过被调函数修改主调函数中一维数组的内容[如何界定]
两个参数:1)存放数组首元素的指针变量;2)存放数组元素长度的整型变量
//Array_point_2.cpp
# include <stdio.h> void Show_Array(int * p, int len) // a发送给了*p
{
// p[0] = -1; //p[0] == *p
// p[2] = -1; //p[2] == *(p+2) == *(a+2) p[i]就是主函数的a[i]
int i = ; for (i=; i<len; ++i)
printf("%d\n", p[i]);
} int main(void)
{
int a[] = {,,,,}; Show_Array(a, ); // a等价于&a[0], &a[0]本身就是i
// 通过写一个数组名,数组长度,就可以确定一个数组,
// 要想通过一个函数,访问另一个函数中的一个数组,只需要知道这个数组的首地址(数组第一个元素地址)和长度,
// 在另一个函数中就可以任意访问、修改主函数a[5]的值
//[Out]:1 2 3 4 5 // printf("%d\n", a[2]);
//[Out]: -1
// printf("%d\n", a[0]);
//[Out]: -1 return ; }
数据结构笔记1(c++)_指针的更多相关文章
- 数据结构笔记2(c++)_跨函数使用内存的问题
预备知识 1.所有的指针变量只占4个子节 用第一个字节的地址表示整个变量的地址 //1.cpp 所有的指针变量只占4个子节 用第一个字节的地址表示整个变量的地址 # include <stdi ...
- C/C++:提升_指针的指针和指针的引用
C/C++:提升_指针的指针和指针的引用 写在前面 今天在使用指针的时候我发现了一个自己的错误.
- C++第四篇--重载_指针_引用
C++第四篇--重载_指针_引用 1. 基础知识 重载:函数名相同,根据参数不同(类型.数量.顺序不同)调用同名函数 指针和引用:引用就是别名,引用时必须初始化,引用你定义的变量. int a; in ...
- 从IL角度彻底理解回调_委托_指针
从IL角度彻底理解回调_委托_指针 目录 从IL角度彻底理解回调_委托_指针 1.创作此文的背景 1.1.委托能帮助代码更好地封装 1.2.委托能随时随地更方便地运行其他类中的方法 1.3.委托非常适 ...
- C++程序设计(第4版)读书笔记_指针、数组与引用
void * 函数指针和指向类成员的指针不能被赋给void * 字符串字面值常量 #include <iostream> using namespace std; void f() { c ...
- Essential C++ 学习笔记02--Array/Vector 与指针
Essential C++ 1.5-1.6节,3.1节笔记 Array/Vector/指针,难度偏大, 但若学习初期不熟悉基本用法,则难以写出有效代码. 1. 基本概念 Array 是一段连续内存,数 ...
- iOS: 学习笔记, Swift与C指针交互(译)
Swift与C指针交互 Objective-C和C API经常需要使用指针. 在设计上, Swift数据类型可以自然的与基于指针的Cocoa API一起工作, Swift自动处理几种常用的指针参数. ...
- 数据结构复习之C语言指针与结构体
数据结构指针复习: #include <stdio.h> void main() { ] = {, , , , }; // a[3] == *(3+a) printf(+a)); // a ...
- c语言学习笔记(9)——指针
指针是c语言的灵魂 ----------------------------------------------------------------------------- # include &l ...
随机推荐
- numpy输出有省略号的问题
发现很多文章都说加一句 np.set_printoptions(threshold="nan") 或者 np.set_printoptions(threshold=np.nan) ...
- 最近学习了Http连接池
起因 6.1大促值班发现的一个问题,一个rpc接口在0~2点用户下单高峰的时候表现rt高(超过1s,实际上针对性优化过的接口rt超过这个值也是有问题的,通常rpc接口里面即使逻辑复杂,300ms应该也 ...
- python语言的鸭子类型和强类型语言的多态
python语言的鸭子类型和强类型语言的多态 前面讲接口类的时候举过一个有关支付方式的例子,支付方式可以有几种,微信支付,支付宝支付,苹果支付等,这几个不同的支付都统一于支付,像这样几个类都统一于 某 ...
- A Code Farmer‘s Entertainment
My guitar playing and singing 码农的自娱自乐 https://v.youku.com/v_show/id_XNDM4NTY1MTEwNA==.html?spm=a2hzp ...
- Github(第一次尝试)
重要提示:项目中的文件最好最好不要出现中文,尤其是复杂的中文文件名. 前提:本地已经用git 管理 一个测试项目(项目一),分支为master. 1.注册 github: http://git.osc ...
- Bandizip解压压缩软件
上次重装系统以后,特别注意安装软件,在这里提一些比较好的 解压软件:Bandizip 这个是一个免费轻量级的软件,压缩解压速度快,没什么广告,推荐大家在官方下载 Bandizip下载网址 点击下载安装 ...
- 关于python的中国历年城市天气信息爬取
一.主题式网络爬虫设计方案(15分)1.主题式网络爬虫名称 关于python的中国城市天气网爬取 2.主题式网络爬虫爬取的内容与数据特征分析 爬取中国天气网各个城市每年各个月份的天气数据, 包括最高城 ...
- VUE中 $on, $emit, v-on三者关系
VUE中 $on, $emit, v-on三者关系 每个vue实例都实现了事件借口 使用$on(eventName)监听事件 使用$emit(eventName)触发事件 若把vue看成家庭(相当于一 ...
- 配置 Elasticsearch 集群
Elasticsearch 的安装非常简单,笔者在前文<单机部署 ELK>中已经介绍过了,本文主要介绍集群的配置,并解释常见配置参数的含义. 要配置集群,最简单的情况下,设置下面几个参数就 ...
- HTML连载54-网易注册界面实战之信息填写
一.完成了内容中的右边的一部分.练习了三点:小盒子在大盒子中的位置,最好用大盒子的内边距完成布局,而不是用小盒子的外边距来进行布局:复习了ul,li的用法. <!DOCTYPE html> ...