数据结构与算法 & 循环数组与通用数组(矩阵)工具 & void * 与void **使用

一、数组的优缺点

1.优点:

1、按照索引查询元素速度快
2、能存储大量数据
3、按照索引遍历数组方便

2.缺点:

1、根据内容查找元素速度慢
2、数组的大小一经确定不能改变。
3、数组只能存储一种类型的数据
4、增加、删除元素效率慢
5、未封装任何方法,所有操作都需要用户自己定义。
摘自文章数组优缺点总结

二、循环数组

1.作用:

为了避免数组的整体移动,使用循环数组。

2.简单说明

将一组数据,标记上两个下标(head)和(tail)。当数据移动时,不需要通过一个个复制,来实现移动。只需要将tail 和head的移动就可以实现。
数据移动: 一组数据中,每次操作会删除或增加新数据,但大部分数据可以保留。

3.实现

  • 下标移动
#define capacity 5
     int array[capacity] = {1,2,3,4,5};
     int head = 0;
     int tail = 0;
     //有效数据12345
     head = 4; // 元素头指针
     //增加6,删除1
     head = (head + 1) % capacity;
     tail = (tail + 1) % capacity;
     array[head] = 6;//增加6
     for (; tail == head; tail = (tail + 1) % capacity) {
          printf("%05d", array[tail]);  //输出23456
     }

head = (head + 1) % capacity; 当 head = capacity - 1 时,操作时,head = 0,形成循环。

4.适用地方

1.贪吃蛇的蛇身数据存储
2.队列工具的实现
3.各种数据移动类

二、通用一维数组

什么是通用一维数组?起码能适用于各种类型。

1.数据类型通用(void *)

思考: 数据类型不同,有长有短,但是数据首地址都是4B。是一样的。
所以使用void *就可以将不同数据的是首地址保存。
那么这个数值可以申请为 *void array[capacity];
采用动态存储分配可以这样:

typedef struct NORMAL_MATRIX {
	void **data;
	int capacity;
}NORMAL_MATRIX;
//初始化
	NORMAL_MATRIX array;
	array.data = (void **) calloc(sizeof(void *), array.capacity);	

void **小解释:

//解释
	typedef struct STU {
		int score;
		...
	}STU;
	void **data = NULL;
	data = (void **)calloc(sizeof(void *), n);
	int num = 30;
	char str[8] = "12345678";
	STU stu1 = {...};//结构体
	data[0] = #
	data[1] = str;  (&str[0] <=> &*(str + 0) <=> str)
	data[2] = stu1;
//下面是图片
	

在这里插入图片描述

三、通用二维数组工具

其实,一维数组明白之后,二维数组也就轻松了。二维数组某种程度称之为二阶矩阵。

1.控制元素

typedef struct NORMAL_MATRIX {
	void **data;
	int rowCount;//行阶
	int colCount;//列阶
}NORMAL_MATRIX;

2.基本功能实现

初始化和销毁:

boolean initMatrix(NORMAL_MATRIX **matrix, int rowCount, int colCount) {
	if (NULL == matrix || NULL != *matrix || rowCount <= 0 || colCount <= 0) {
		return FALSE;
	}
	*matrix = (NORMAL_MATRIX *) calloc(sizeof(NORMAL_MATRIX), 1);
	if (NULL == *matrix) {
		return FALSE;
	}
	(*matrix)->data = (void **) calloc(sizeof(void *), rowCount * colCount);
	if (NULL == (*matrix)->data) {
		free(*matrix);
		*matrix = NULL;
		return FALSE;
	}
	(*matrix)->rowCount = rowCount;
	(*matrix)->colCount = colCount;

	return TRUE;
}
//销毁二维数组(矩阵)
void destory(NORMAL_MATRIX **matrix) {
	if (NULL == matrix ||NULL == *matrix) {
		return;
	}
	free((*matrix)->data);
	free(*matrix);
	*matrix = NULL;
}

存储数与读取数:

//指定下标率录入元素
boolean setElementAt(const NORMAL_MATRIX *matrix, const int row, const int col, void *data) {
	if (NULL == matrix 
			|| row < 0 || row >= matrix->rowCount 
			|| col < 0 || col >= matrix->colCount
			|| NULL == data) {
		return FALSE;
	}
	matrix->data[row * matrix->colCount + col] = data;
	return TRUE;
}
//指定下标读取数据
void *getElementAt(const NORMAL_MATRIX *matrix, const int row, const int col) {
	if (NULL == matrix
			|| row < 0 || row >= matrix->rowCount 
			|| col < 0 || col >= matrix->colCount) {
		return FALSE;
	}
	return matrix->data[row *matrix->colCount + col];
}

ps:二维数组本质也是一维数组,所以这里只要处理好一维数组下标与二维数组之间关系就可以了。

四、总结

  1. 每一中数据结构都有其优缺点。更有其适用地方。灵活应用,才能更好解决问题。
  2. void* 的得到,属于对各个数据求同的结果。刚开始还模糊,用的多了就越来越得心易手。
  3. 通用。

笔者水平有限,目前只能描述以上问题,如果有其他情况,可以留言,有错误,请指教,有继续优化的,请分享,谢谢!
完整代码如下:
matrix.h:

#ifndef _SL_MATRIX_H_
#define _SL_MATRIX_H_

#define TRUE   1
#define FALSE  0

typedef unsigned char boolean;
typedef struct NORMAL_MATRIX {
	void **data;
	int rowCount;
	int colCount;
}NORMAL_MATRIX;

boolean initMatrix(NORMAL_MATRIX **matrix, int rowCount, int colCount);
void destory(NORMAL_MATRIX **matrix);
boolean setElementAt(const NORMAL_MATRIX *matrix, const int row, const int col, void *data);
void *getElementAt(const NORMAL_MATRIX *matrix, const int row, const int col);
#endif 

matrix.c:

#include <stdio.h>
#include <malloc.h>

#include "matrix.h"
//初始化二维数组(矩阵)
boolean initMatrix(NORMAL_MATRIX **matrix, int rowCount, int colCount) {
	if (NULL == matrix || NULL != *matrix || rowCount <= 0 || colCount <= 0) {
		return FALSE;
	}
	*matrix = (NORMAL_MATRIX *) calloc(sizeof(NORMAL_MATRIX), 1);
	if (NULL == *matrix) {
		return FALSE;
	}
	(*matrix)->data = (void **) calloc(sizeof(void *), rowCount * colCount);
	if (NULL == (*matrix)->data) {
		free(*matrix);
		*matrix = NULL;
		return FALSE;
	}
	(*matrix)->rowCount = rowCount;
	(*matrix)->colCount = colCount;

	return TRUE;
}
//销毁二维数组(矩阵)
void destory(NORMAL_MATRIX **matrix) {
	if (NULL == matrix ||NULL == *matrix) {
		return;
	}
	free((*matrix)->data);
	free(*matrix);
	*matrix = NULL;
}
//指定下标率录入元素
boolean setElementAt(const NORMAL_MATRIX *matrix, const int row, const int col, void *data) {
	if (NULL == matrix 
			|| row < 0 || row >= matrix->rowCount 
			|| col < 0 || col >= matrix->colCount
			|| NULL == data) {
		return FALSE;
	}
	matrix->data[row * matrix->colCount + col] = data;

	return TRUE;
}
//指定下标读取数据
void *getElementAt(const NORMAL_MATRIX *matrix, const int row, const int col) {
	if (NULL == matrix
			|| row < 0 || row >= matrix->rowCount 
			|| col < 0 || col >= matrix->colCount) {
		return FALSE;
	}
	return matrix->data[row *matrix->colCount + col];
}

2020年03.07 家

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值