C生万物 | 从浅入深理解指针【第二部分】(一):https://developer.aliyun.com/article/1426624
4. 冒泡排序
接下来我们就学习一下这个冒泡排序,主要学习两个内容~~
- 学习冒泡排序
- 学习数组传参
- 我们给了这样的一个降序数组,我们需要将这个数组排序,排为升序
int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; //进行排序 return 0; }
- 我们创建一个函数,要排的是谁呢?是arr
int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; //进行排序 int sz = sizeof(arr) / sizeof(arr[0]); sort(arr,sz); return 0; }
- 我们这里要讲一种排序,是冒泡排序
- 冒泡排序的核心思想就是:两两相邻的元素进行比较。
代码如下:
void 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(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } } int main() { int arr[] = { 9,8,7,6,5,4,3,2,1,0 }; //进行排序 int sz = sizeof(arr) / sizeof(arr[0]); sort(arr,sz); print(arr, sz); return 0; }
- 上面的代码也可以指针的形式,还是一样的道理~~
- 上面的代码还是有优化的空间的,假设我的数组是这样的:
int arr[] = { 9,0,1,2,3,4,5,6,7,8 };
- 这里我们经过一趟冒泡排序后就已经排好了,但是我们上面的代码一定要进行9趟,我们不进行交换,但还是要执行,效率是比较低的
- 如果已经排成有序的了,那后面就不用排了,那怎么做呢?
void sort(int arr[], int sz) { //确定冒泡排序的趟数~~ int i = 0; for (i = 0; i < sz - 1; i++) { //一趟冒泡排序 int j = 0; int flag = 1;//假设数组是有序的 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; flag = 0;//不是有序 } } if (flag = 1) { break; } } }
- 这样的写法是不是更好~~
5. 二级指针
- 指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里?
- 我们来看下面的这一段代码~~
#include<stdio.h> int main() { int a = 10; int* pa = &a; int** ppa = &pa; return 0; }
- a是整形变量,占用4个字节空间,a是自己的地址,&a拿到的就是a所占4个字节的第一个字节的地址
- pa是指针变量,占用4/8个字节的空间,p也是有自己的地址,&p就拿到了p的地址,pa是一级指针
- ppa也是指针变量,ppa是二级指针变量
- 那么我们能不能&ppa呢?可以啊,ppa也是有自己的地址,&ppa就拿到了ppa的地址,放到一个三级指针–>
int*** pppa = &ppa
- 这些变量都是普通的变量,不要看的很厉害~~
- 我们可以调试起来画图了解一下~~
对于二级指针的运算有:
*ppa
通过对ppa
中的地址进行解引用,这样找到的是pa
, *ppa
其实访问的就是
int b = 20; *ppa = &b;//等价于 pa = &b;
**ppa
先通过*ppa
找到pa
,然后对pa
进行解引用操作: *pa
,那找到的是a
.
**ppa = 30; //等价于*pa = 30; //等价于a = 30;
6. 指针数组
- 什么是指针数组?
我们类比一下:
- 整形数组:存放整形的数组 int arr[10];
- 字符数组:存放字符的数组 char ch[5];
- 指针数组:存放指针的数组
整形数组和字符数组:
指针数组的每个元素都是用来存放地址(指针)的。
如下图:
指针数组的每个元素是地址,又可以指向一块区域。
比如:
int main() { int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; int* parr[5] = { &a,&b,&c,&d,&e }; return 0; }
- 那我们也是可以打印出来的
int main() { int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; int* parr[5] = { &a,&b,&c,&d,&e }; int i = 0; for (i = 0; i < 5; i++) { printf("%d ", *(parr[i])); } return 0; }
parr[i]
找到了每个元素的地址,然后解引用,就找到了,便可以打印出来~~
7. 指针数组模拟二维数组
#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; }
parr[i]
是访问parr数组的元素,parr[i]
找到的数组元素指向了整型一维数组,parr[i][j]
就是整型一维数组中的元素。
上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。- 如果不懂还可以看下图: