动态内存分配实现二维数组 和 qsort模拟实现(冒泡排序)

今天我们来讲两道十分基础的基础题

动态内存分配实现二维数组

在实现这个程序之前,我们需要了解二维数组究竟是什么?
不管二维数组还是三维还是四维……它们本质上都是一维数组。什么意思呢?
我们创建一个一维数组,数组的元素还是数组,那它就可以是二维数组,如果数组中的数组的元素还是数组,那它就是一个三维数组……
因此,我们要用动态内存分配实现二维数组,我们需要先开辟一片空间(堆区),这些空间存储的元素是指针,分别指向不同的空间。
在这里插入图片描述
那好,我们现在就开始创建一个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

成功。

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值