知识特点(学习方向)
上一篇是最基础概念,这一篇将涉及 如何⽤指针访问数组,⼀维数组传参,冒泡排序,⼆级指针, 指针数组, 指针数组模拟⼆维数组等更深入的一些知识点,每篇内容不多很好理解,相信大家看完这几篇之后会对指针的理解有质的飞跃
深入理解未来会继续连更4篇,如果需要可以先关注。
每一个知识点都讲的很细节,已经学明白并掌握第一节指针基础知识点合集1的同学让我们一起继续深一步的学习。
多运用类比,希望大家能和前面知识点联系起来,多比较,多研究,祝大家学习愉快。
1.数组名的理解(比赛题常考点)
数组是什么,数组名就是首元素地址嘛??(你和数组心连心,数组对你伤脑筋)
先自己检测一下能否分清以下数组含义吧!
sizeof(arr)
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
printf("arr[1] = %p\n", arr[1]);
arr[1];
其实数组名就是数组⾸元素(第⼀个元素)的地址是对的,但是有两个例外:
• sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节。
• &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素 的地址是有区别的)
除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。
1.1区分arr和&arr
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("&arr[0] = %p\n", &arr[0]);
printf("&arr[0]+1 = %p\n", &arr[0]+1);
printf("arr = %p\n", arr);
printf("arr+1 = %p\n", arr+1);
printf("&arr = %p\n", &arr);
printf("&arr+1 = %p\n", &arr+1);
return 0;
}
结果如下:
解释:我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因为&arr[0]和arr都是 ⾸元素的地址,+1就是跳过⼀个元素.但是&arr和&arr+1相差40个字节,这就是因为&arr是数组的地址,+1操作是跳过整个数组.
2.使⽤指针访问数组
前面介绍过指针基础概念后,这一篇我们主要讲基础运用。
举例:
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);//需要数组长度因此需要先计算出元素个数
int* p = arr;//数组名等于首元素地址!!!
for (i = 0; i < sz; i++)
{
scanf_s("%d", p + i);
}
for (i = 0; i < sz; i++)
{
printf("%d", *(p + i));
}
return 0;
}
将*(p+i)换成p[i]也是能够正常打印的,本质上p[i]是等价于*(p+i)
3.⼀维数组传参的本质
数组名是数组⾸元素的地址;那么在数组传参 的时候,传递的是数组名,也就是说本质上数组传参传递的是数组⾸元素的地址
void test(int arr[])//参数写成数组形式,本质上还是指针 ,数组名是首元素地址,依然是指针
{
printf("%d\n", sizeof(arr));
}
void test(int* arr)//参数写成指针形式
{
printf("%d\n", sizeof(arr));//计算⼀个指针变量的⼤⼩
}
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
test(arr);
return 0;
}
⼀维数组传参,形参的部分可以写成数组,也可以写成指针的形式。
4.⼆级指针
指针变量也是变量
是变量就有地址,那指针变量的地址存放在哪⾥? 这就是 ⼆级指针(一级指针变量的地址)
举例子:
**ppa 先通过 *ppa 找到 pa ,然后对 pa 进⾏解引⽤操作: *pa ,那找到的是 a
**ppa = 30;
//等价于*pa = 30;
//等价于a = 30;
5.指针数组
整型数组,是存放整型的数组,字符数组是存放字符的数组
指针数组呢?是存放指针的数组
指针数组的每个元素是地址,⼜可以指向⼀块区域
指针数组的每个元素都是⽤来存放地址(指针)的
6.指针数组模拟⼆维数组
(二维数组实际上就是多个一维数组构成的数组)
#include <stdio.h>
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {2,3,4,5,6};
int arr3[] = {3,4,5,6,7};
//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中
int* parr[3] = {arr1, arr2, arr3};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
7.冒泡排序(十分详细重要排序算法题,后期排序算法也会出合集))
7.1冒泡排序的思想
两两相邻元素比较,按照降序或者升序,如果不满足顺序就交换,满足顺序就找下一对儿
例如上图
1.若有n个元素,最坏的情况需要进行n-1趟冒泡排序:说明需要元素个数
2.每一对儿都需要相互比较
7.2冒泡排序实现过程(解析看不懂后台私信或评论都可以 随时解答)
1.首先定义题中已给数据(例如数组)
2.因为我们需要确定排序多少趟,怎么循环,所以需要计算一下数组元素个数int sz = sizeof(arr) / sizeof(arr[0]);
3.以上为准备工作,那么实现冒泡时我们可以分装一个函数bubble_sort(arr,sz)(数组和元素个数传过去
4.冒泡排序中,需要用循环for来表示循环排序过程(for (i = 0; i < sz - 1; i++))(我们已经分析,若有n个元素,最坏的情况需要进行n-1趟冒泡排序)进入每趟循环后,例如第一趟循环,第一个元素需要跟每一个元素比较那么这个比较也需要循环因此我们还需要一层循环
5.第二层循环中需要和每个元素比较大小for (j = 0; j <sz-1-i; j++)(例如第一趟是10个元素,需要进行8次相互比较(例如:9 8 7 6 5 4 3 2 1 0,那么9和8比,9和7比.......等等等等),所以就需要使用if来进行判断if (arr[j] > arr[j + 1])。
6.实现完冒泡排序之后需要输出,可以再封装一个函数,根据for循环依次进行输出打印(这个不懂的话是for循环的知识点)
//对一个数组中的元素实现升序的冒泡排序
void bubble_sort(int arr[],int sz)//不需要任何返回值,只用排序就行
{
int i = 0;
for (i = 0; i < sz - 1; i++)//循环趟
{
//一趟冒泡排序
int j = 0;
for (j = 0; j <sz-1-i; j++)
{
if (arr[j] > arr[j + 1])//判断是否满足升序
{//不满足就交换
int tmp = arr[j];//注意定义中间变量
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
void print_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
printf("\n");
}
#include<stdio.h>
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);//封装进入一个函数内
print_arr(arr, sz);//封装一个函数进行打印
return 0;
}
指针形式:
//对一个数组中的元素实现升序的冒泡排序
void bubble_sort(int *arr,int sz)//不需要任何返回值,只用排序就行
{
int i = 0;
for (i = 0; i < sz - 1; i++)//循环趟
{
//一趟冒泡排序
int j = 0;
for (j = 0; j <sz-1-i; j++)
{
if (*(arr+j) > arr[j + 1])//判断是否满足升序
{//不满足就交换
int tmp = *(arr + j);//注意定义中间变量
*(arr + j) = *(arr+j + 1);
*(arr+j + 1) = tmp;
}
}
}
}
void print_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
printf("\n");
}
#include<stdio.h>
int main()
{
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr,sz);//封装进入一个函数内
print_arr(arr, sz);//封装一个函数进行打印
return 0;
}
7.3优化代码
以上方式即使一开始就,因此我们可以先假设元素本身就是有序的,如果不满足
再进行排列
1.加入flag通过flag避免那种本身就符合顺序的元素
2.加入count来检验看程序是否这样更加优化
//对一个数组中的元素实现升序的冒泡排序
int count = 0;//可以看排序了几趟,这样可以比较优化效果
void bubble_sort(int arr[], int sz)//不需要任何返回值,只用排序就行
{
int i = 0;
for (i = 0; i < sz - 1; i++)//循环趟
{
int flag = 1;//假设有序
//一趟冒泡排序
int j = 0;
for (j = 0; j < sz - 1 - i; j++)
{
count++;// 进行比较就++
if (arr[j] > arr[j + 1])//判断是否满足升序
{//不满足就交换
int tmp = arr[j];//注意定义中间变量
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
flag = 0;//有交换就为0;
}
}
if (flag == 1)
{
break;
}
}
}
void print_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d", arr[i]);
}
printf("\n");
}
#include<stdio.h>
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
int sz = sizeof(arr) / sizeof(arr[0]);
bubble_sort(arr, sz);//封装进入一个函数内
print_arr(arr, sz);//封装一个函数进行打印
printf("count=%d", count);
return 0;
}
优化后与先前对比图:
完—
今天的分享就先到这里,每篇涉及的知识点不是很多但都十分相信,希望对大家有所帮助,有什么问题或者指教都可以提出来哈,记得点赞关注哦!
小预告(明日老时间分享):
1.字符指针变量
2. 数组指针变量
3. ⼆维数组传参的本质
4. 函数指针变量
5. 函数指针数组
6. 转移表
7.assert断言
等内容
祝大家工作顺利,学业有成!!!