今天我们来讲两道十分基础的基础题
动态内存分配实现二维数组
在实现这个程序之前,我们需要了解二维数组究竟是什么?
不管二维数组还是三维还是四维……它们本质上都是一维数组。什么意思呢?
我们创建一个一维数组,数组的元素还是数组,那它就可以是二维数组,如果数组中的数组的元素还是数组,那它就是一个三维数组……
因此,我们要用动态内存分配实现二维数组,我们需要先开辟一片空间(堆区),这些空间存储的元素是指针,分别指向不同的空间。
那好,我们现在就开始创建一个5*3的数组
首先我们要先开辟一片空间p
int** p = (int**)malloc(sizeof(int*) * 5);
if (p == NULL)//检测空间是否开辟成功,若失败,返回错误原因,并结束函数
{
perror("malloc");
return 1;
}
注意,我们的空间存储的信息是指针,而变量p指向又是这片空间的地址,因此我们p是一个指针的指针,因此其类型为 (int**).
接下来,我们要遍历这片空间,使这个空间里每个元素指向其它空间的地址。
int i = 0;
for (i = 0; i < 5; i++)
{
*(p + i) = (int*)malloc(sizeof(int) * 3);
if (*(p+i) == NULL)
{
perror("malloc");
return 1;
}
}
好了,这个二维数组已经创建完了,是不是很简单?
接下来我们来检验一下
int j = 0, k = 0;
for (j = 0; j < 5; j++)
{
for (k = 0; k < 3; k++)
{
p[j][k] = j + k;
}
}
for (j = 0; j < 5; j++)
{
for (k = 0; k < 3; k++)
{
printf("%d ",p[j][k]);
}
printf("\n");
}
答案正确
0 1 2
1 2 3
2 3 4
3 4 5
4 5 6
注意!!!一定要记得释放内存
for (i = 0; i < 5; i++)
{
free(*(i + p));
*(i + p) = NULL;
}
free(p);
p = NULL;
qsort模拟实现(冒泡排序法)
qsort函数可以实现任何类型数组的排序,它需要我们自己根据数组类型创建一个比较大小的函数
我们先来看看c语言怎么声明qsort函数
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));
base
Pointer to the first object of the array to be sorted, converted to a void*.
//指向需要排序的数组(注意是void*类型)
num
Number of elements in the array pointed to by base.
size_t is an unsigned integral type.
//数组中元素的数量
size
Size in bytes of each element in the array.
size_t is an unsigned integral type.
//每个元素的大小(单位是字节bytes)
compar
Pointer to a function that compares two elements.
This function is called repeatedly by qsort to compare two elements.
//一个函数指针,用于判断两个同类型数据的大小
我们先来理解下参数中的函数指针 (* compar)(const void*,const void*)
这个函数就是我们自己创建的,它要求先后传入两个参数,若第一个参数大于第二个,则返回>0;若第一个参数小于第二个,则返回<0;若第一个等于第二个,则返回0.我们来举个例子(char类型)
int (char_compar)(const void* n1,const void* n2)
{
return *(char*)n1 - *(char*)n2;
}
现在就让我们来实现qsort函数
我们先写出基本框架
void my_qsort(void* arr, size_t num, size_t size, int(*compar)(void*, void*))
{
int i, j = 0;
for (i = 0; i < num - 1; i++)
{
for (j = 0; j <num- i - 1; j++)
{
if (compar((char*)arr + j * size, (char*)arr + (j + 1) * size) > 0)
{
swap((char*)arr + j * size, (char*)arr + (j + 1) * size , size);
}
}
}
}
注意,我们传入的数组参数是void类型,因此为了比较两个元素,我们可以把它转化成char类型,再通过加上size*j,去获得比较那个元素;在程序知道两个元素的大小之后,就可以判断是否使用swap来交换两个值;
swap(char* p1, char* p2, size_t size)
{
for (int i = 0; i < size; i++)
{
char k = *(p1 + i);
*(p1 + i) = *(p2 + i);
*(p2 + i) = k;
}
}
因为如果运行swap就一定会交换两个值,因此在swap函数内部,我们可以以字节为单位,来依次交换对应的两个字节的值。
好了,qsort也实现了,是不是还是很简单。
接下来,我们来看看完整的函数,并检查运行效果
swap(char* p1, char* p2, size_t size)
{
for (int i = 0; i < size; i++)
{
char k = *(p1 + i);
*(p1 + i) = *(p2 + i);
*(p2 + i) = k;
}
}
void my_qsort(void* arr, size_t num, size_t size, int(*compar)(void*, void*))
{
int i, j = 0;
for (i = 0; i < num - 1; i++)
{
for (j = 0; j <num- i - 1; j++)
{
if (compar((char*)arr + j * size, (char*)arr + (j + 1) * size) > 0)
{
swap((char*)arr + j * size, (char*)arr + (j + 1) * size , size);
}
}
}
}
int int_compare(void* n1, void* n2)
{
return (*(int*)n1 - *(int*)n2);
}
int main()
{
int arr[] = { 32,42,12,53,12,4,6,1 };
my_qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(arr[0]), int_compare);
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
1 4 6 12 12 32 42 53
成功。