目录
指针
指针概念
指针就是地址,地址就是数据在内存单元的编号
当指针为a时,指的是指针变量;当指针为0x1000时,指针指的是地址
指针也是一种数据类型,指针类型是专门来处理地址这种数据的;
指针变量
语法:基类型 *指针变量名
基类型
整型,浮点型,字符型,数据类型,指针类型,结构体类型,函数类型;
作用:用来表示这个指针类型指向的内存空间存放的是什么类型的数据;
*
定义的时候,表示此时定义的是一个指针类型的变量;
指针变量名
符号标识符命名的规则
int a = 10; //a所在的空间是用来存放int类型的数据的
int *p = &a; //此时p指向了a
&a表示获得a所在空间的首地址;表示获得了一块可以存放int类型的内存空间地址。
指针类型
int *p;
(int *)就是指针类型
int * p 它首先表示的是一个指针类型,然后再表示指向int型数据的指针类型。
指针变量的引用
int a=10;
int *p = &a; //p指向a,因为保存了a的地址
*是指针运算符,也是单目运算符,它的运算对象只能是指针(地址);
*p表示访问p所执行的基类型的内存空间
*p间接访问;通过a访问的是直接访问
访问步骤:1.首先拿出p中地址,到内存中定位;2.偏移出sizeof(基类型)大小的一块空间;
3.将偏移出的这块空间,当做一个基类型来看(*p运算完的效果)
*p运算效果就相当于是一个基类型的变量,整体等价来看*p等价于a。
指针变量初始化
如果指针变量没有初始化,此时是随机值(野指针)
初始化可以让指针变量,有明确指向
int *p = NULL; //0号地址(空指针)
赋值
int *p;
p = NULL;
int a;
int *p;
p = a;
定义多个指针
错误
int *p,q; //p是指针int*类型,q是int型
正确
int *p,*q; //此时定义了两个int*类型的变量p和q
注意:定义时候的*是修饰变量名的,表示的是定义一个指针类型的变量。
示例
求两个数的和
#include<stdio.h>
void add(int a , int b,int *sum)
{
*sum= a + b;
}
int main(void)
{
int a = 2;
int b = 3;
add(a,b,&sun);
printf("sum = %d",sum);
}
求两个数的最大最小值
#include<stdio.h>
void maxoftwo(int a,int b,int *max,int *min)
{
if(a>b)
{
*max = a;
*min = b;
}
else
{
*max = b;
*min = a;
}
}
int main(void)
{
int a =2;
int b=3;
int max;
int min;
maxoftwo(a,b,&max,&min);
printf("max = %d min = %d",max,min);
return 0;
}
两个数交换
void swap(int *a,int *b)
{
int t= *b;
*b = *a;
*a = t;
}
int main(void)
{
int a =2;
int b =3;
swap(&a,&b);
printf("a = %d b = %d\n",a,b);
return 0;
}
需要指针的原因是指针可以被调修改住调(指针80%都是这样用
实现被调修改主调
1.指针作为函数参数
形参—指针类型变量用来接受实参(实参是要操作的内存空间的地址);
实参—要修改谁,就把谁的地址传过去,要保证空间有效,不能是野指针;
注意:被调函数中,一定要有*p运算,间接访问操作。
值传递:只是实参数据赋值了形参
地址(指针)传递:传的是地址,可以实现被调修改主调。
注意:在创建函数定义形参的时候一定要分清楚哪些是需要值传递,哪些是需要地址(指针)传递。
指针的运算
&
*
*&a 等价于 a 等价于 *p
&*p 等价于 &a
p+n —加n表示跳过了n个基类型
p-n
p++
p--
访问数组时
a[i]本质上是指针运算
*(p+i)等价于 a[i] 等价于 *(a+1)
i[a] 等价于 *(i+a)
所以数组可以用函数中的式子打印
#include<stdio.h>
void printArray(int *a,int len)
{
int i=0;
for(i=0;i<len;i++)
{
printf("a[%d]= %d\n",i,*a++);
printf("a[%d]= %d\n",i,*(a+i));
printf("a[%d]= %d\n",i,*(i+a));
printf("a[%d]= %d\n",i,a[i]);
printf("a[%d]= %d\n",i,i[a]);
}
}
指针还可以做关系运算
< > != == <= >=;
p-q表示比较差了多少元素(基类型),两个必须是同一类型的指针;
p+q不能这样表示,没有意义;
指针+一维整型数组
int a[5]; 一维整型数组;
数组名:类型为数据类型int [5];值为数组首元素的地址,是一个常量不能进行自增自减
int *p = &a[0];
int *p = a; //表示p指向数组
数组名就是数组首元素的地址
这个地址的类型是int * 所以a等价于&a[0];
数组作为函数参数
形参—数组形式+数组长度
int *a,int len;数组形式本质上是一个指针类型变量;
实参 数组名+数组长度
数组名代表数组首地址;
一些指针代码示例
用指针实现找出两个数最大值函数
#include<stido.h>
void maxnum(int *a,int len)
{
int i;
int max = *a;
for(i=0;i<len;i++)
{
if(max < *(a+i))
max = *(a+i);
}
printf("max = %d\n",max);
}
交换两个数函数
void swap(int *a,int *b)
{
int t= *b;
*b = *a;
*a = t;
}
指针实现选择排序函数
void choiesort(int *begin,int *end)
{
int *p = begin;
int *q = NULL;
for(p=begin;p<end;++p)
{
for(q=p+1;q<=end;++q)
{
if(*q > *p)
swap(q,p);
}
}
}
指针实现冒泡排序函数
void bubblesort(int *begin,int *end)
{
int *p = begin;
int *q = NULL;
for(p=end;p>begin;--p)
{
for(q=begin;q<p;++q)
{
if(*q > *(q+1))
swap(q,q+1);
}
}
}
指针实现插入排序函数
void intersort(int *begin,int *end)
{
int *p = begin;
int *q = NULL;
for(p=begin;p<=end;++p)
{
int t = *p;
q=p;
while(q>begin&&t<*(q-1))
{
*q = *(q-1);
--q;
}
*q =t;
}
}
指针实现二分查找函数
int *binaryFind(int *begin,int *end ,int n)
{
int *mid = NULL;
int *ret = NULL;
while(begin<=end)
{
*mid=begin+(end - begin)/2;
if(n>*mid)
mid = begin +1;
else if(n<*mid)
mid = end -1;
else
ret = mid;
}
return ret;
}
迭代的方法实现倒序函数
void reverse(int *begin,int *end)
{
while(begin< end)
{
swap(begin,end);
++*begin;
--*end;
}
}
快速排序
思想:分而治之
实现思路
1.基准值—就是数组首元素a[0]位置的值,a[0]这个位置也叫基准值位置
2.end 从右边开始找,找到第一个比基准值小的数,然后停止找
3.begin 从左边开始找,找到第一个比基准值大的数,然后停止
4.将找到这两个数交换位置,继续重复2-4的过程,直到begin与end相遇,此时这个过程结束结束。
5.将基准位置上值与此时begin与end所谓位置的元素交换
6.继续对左一半和右一半进行快速排序,直到最后一次begin和end一开始找就在一个位置上
流程图
实现代码函数
void quicksort(int *begin,int *end)
{
int *p = begin;
int *q = end;
int *k = begin;
if(begin>=end)
return;
while(begin<end)
{
while(begin<end && *k<=*end)
--end;
while(begin<end && *k>=*begin)
++begin;
swap(begin,end);
}
swap(k,begin);
quicksort(p,end-1);
quicksort(begin+1,q);
}