动态开辟二维数组的两种方案及位体
先来回顾一下动态开辟一位数组的方法:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int n = 0;
int* ip = nullptr;
scanf_s("%d", &n);
ip = (int*)malloc(sizeof(int) * n);
if (nullptr == ip)exit(1);
for (int i = 0; i < n; ++i)
{
ip[i] = i;
}
free(ip); //结束后要记得释放内存;
ip = nullptr;//将指针置空,防止出现野指针;
return 0;
}
一、在静态二维数组中查询数据
- 使用范围:二维数组中上一行最后一个数据小于下一行第一个数据。即a<b,c<d的情况。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int FindValue(int(*br)[4], int row, int col, int val) //本质上讲是二分查找;
{
assert(br != nullptr);
int pos = -1;
int* p = (int* )br;
int left = 0, right = row * col - 1;
while (left <= right)
{
int mid = (right - left) / 2 + left;
if (val < p[mid])
{
right = mid - 1;
}
else if (val > p[mid])
{
left = mid + 1;
}
else
{
pos = mid;
break;
}
}
return pos;
}
int main()
{
int ar[3][4] = { 12,23,34,45,56,67,78,89,90,100,110,120 };
int val[] = { 23,100,34,8,80,130 }; //测试的数据;
for (int i = 0; i < sizeof(val) / sizeof(val[0]); i++)
{
int pos = FindValue(ar, 3, 4, val[i]);
if (pos != -1)
{
printf("row=%d col=%d\n", pos / 4, pos % 4); //打印所测数据的行和列;
}
else
{
printf("find not\n");
}
}
return 0;
}
运行结果:
因为静态二维数组在内存中是连续存放的,所以可以用二分查找。
二、动态开辟二维数组空间
1.用二级指针的方式开辟
方法:先申请连续的指针类型的空间,指针再申请空间。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int main()
{
int** br = nullptr; //申请一个二级指针;
int row = 0, col = 0;
scanf_s("%d %d", &row, &col);
br = (int**)malloc(sizeof(int*) * row); //用二级指针动态申请空间,用来存放一级指针;
if (nullptr == br) exit(1);
for (int i = 0; i < row; i++) //动态为连续的一级指针申请空间;
{
br[i] = (int*)malloc(sizeof(int) * col);//申请到的空间存放整型数据;
if (nullptr == br[i]) exit(1);
}
for (int i = 0; i < row; i++) //初始化所申请的空间;
{
for (int j = 0; j < col; j++)
{
br[i][j] = i + j;
}
}
for (int i = 0; i < row; i++) //打印二维数组;
{
for (int j = 0; j < col; j++)
{
printf("%5d", br[i][j]);
}
printf("\n");
}
printf("\n");
for (int i = 0; i < row; i++) //释放动态申请的空间;
{
free(br[i]);
br[i] = nullptr;
}
free(br);
br = nullptr;
return 0;
}
运行结果:
注意:此种方式申请空间时访问数据的形式和静态方式申请访问数据形式有本质区别:
2.用结构体的方式开辟
和顺序表的方法类似,开辟出来的空间是连续的。
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
struct BinArray
{
int* data; //用来开辟动态内存的指针;
int row;
int col;
};
void Init_BinArray(struct BinArray* bp, int r, int c)//初始化函数
{
assert(bp != nullptr);
bp->row = r;
bp->col = c;
bp->data = (int*)malloc(sizeof(int) * c * r);//确定开辟空间的大小;
if (bp->data == nullptr)exit(1);
}
void SetValue(struct BinArray* bp, int r, int c , int val) //赋值函数
{
assert(bp != nullptr && r <= bp->row && c <= bp->col);
bp->data[r * bp->col + c] = val; //模拟二维数组赋值形式;
}
int GetValue(struct BinArray* bp, int r, int c) //获取数据函数
{
assert(bp != nullptr && r <= bp->row && c <= bp->col);
return bp->data[r * bp->col + c]; //模拟二维数组获取数据形式;
}
void DestroyBinArray(struct BinArray* bp) //销毁函数;
{
assert(bp != nullptr);
free(bp->data);
bp->data = nullptr;
bp->col = -1;
bp->row = -1;
}
int main()
{
BinArray br;
int r, c;
scanf_s("%d %d", &r, &c);//输入想要的行数和列数;
Init_BinArray(&br, r, c);
for (int i = 0; i < r; i++) //给二维数组赋值;
{
for (int j = 0; j < c; j++)
{
SetValue(&br, i, j, i + j);
}
}
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
printf("%5d", GetValue(&br,i,j));
}
printf("\n");
}
printf("\n");
DestroyBinArray(&br);
return 0;
}
运行结果:
三、位体
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
struct Node
{
char tag : 4;
//char :0; //告诉编译器,tag和sev不在同一个字节中,存储时,sev会重新存入一个字节;
unsigned char sev : 3;
char tall : 5;
};
int main()
{
struct Node x = {};
x.tag = 8;
x.sev = 7;
x.tall=-8;
return 0;
}
当第一个字节存储位不够存储tall时,tall会另存一个字节,并且也是按照4个比特位读取,-8在内存中会显示01 80;