数据结构4.1 - 数组 基础

1. 数组基础

一维、二维数组
二维数组:行优先、列优先

例题:二维数组A[6][10],每个数组元素占4个存储单元,按行优先,A[3][5]的存储地址是1000,求A[0][0]的存储地址?
3*10 + 5 = 35(个存储单元)
1000 - 35 * 4 = 860

1.1 定义初始化 + 赋值 + 求长度

初始化 参见:https://blog.csdn.net/qq_40893824/article/details/105874127
赋值 + 求长度 参见:https://blog.csdn.net/qq_40893824/article/details/105753917

2. 矩阵压缩存储

2.1 矩阵

转置、相加、相乘

2.2 特殊矩阵 和 稀疏矩阵

2.2.1 特殊矩阵:对称阵 、 三角阵 、 对角阵

(1) 对称阵 (下三角)

(2) 三角阵(下三角)

(3) 对角阵

2.2.2 稀疏阵

顺序存储:1 三元组,2 伪地址;
链式:1 邻接表,2 十字链表

2.2.2.1 三元组
#include<bits/stdc++.h> 
using namespace std;

typedef struct 
{
	int val;
	int i, j;
}Trimat;
//在主函数中定义 Trimat trimat[m + 1] ; m的意思:m个非0元素,1是第一行存储非0元素个数 和 几维矩阵 

// 可简单直接定义二维数组为三元组 int trimat[m + 1][3];
// float类型的元素则:float trimat[m + 1][3];
// 下标:(int) trimat[k][1]; 和  (int) trimat[k][2];
int main()
{
	return 0;
}

矩阵 用 三元组存储:

代码:

#include<bits/stdc++.h> 
#define max 100
using namespace std;

void print(float a[][4], int m, int n)
{
	cout << "输出数组:" << endl; 
	int i, j;
	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

void print2(float trimat[][3])
{
	int i, j, k = 1;
	for(i = 0; i < trimat[0][1]; i++)
	{
		for(j = 0; j < trimat[0][2]; j++)
		{
			if(i == (int)trimat[k][1] && j == (int)trimat[k][2])
			{
				cout << trimat[k][0] << " ";
				k++;
			}
			else
				cout << "0" << " ";
		}
		cout << endl;
	}
}

void creat(float trimat[][3], float a[][4], int m, int n)
{
	int i, j, k = 1;
	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n ; j++)
		{
			if(a[i][j] != 0)
			{
				trimat[k][0] = a[i][j];
				trimat[k][1] = i;
				trimat[k][2] = j;
				k++;
			}
		}
	}
	trimat[0][0] = k-1;
	trimat[0][1] = m;
	trimat[0][2] = n;
	cout << "三元组创建成功!" <<endl <<endl;
}

int main()
{
	float a[4][4] = {{0,0,0,1},{0,0,3,2},{1},{0,1}};
	print(a, 4, 4);
	
	float trimat[max][3];
	creat(trimat, a , 4, 4);
	
	cout << "三元组输出:" <<endl;
	print2(trimat);
	
	return 0;
}
2.2.2.2 伪地址

元素值 + 地址
其中 地址 = n(i - 1) + j,可按行优先 或 列优先

2.2.2.3 邻接表
2.2.2.4 十字链表

结点:

row 行号
col 列号
val 值
down 下指针
right 右指针

十字链表:

左上角结点是 头结点,其它的是 普通结点

代码

思路:

  1. 初始化头结点
  2. 分配空间
  3. 辅助链表(下面的,指针指向右)

注意结点结构体 定义时,各参数的含义!

#include<bits/stdc++.h> 
#define max 100
using namespace std;

typedef struct QNode // 普通结点 
{
	int row, col; // 行号、列号 
	float val; // 值 
	struct QNode *down, *right; //指向 下 和 右 的指针 
}*Link, QNode;

typedef struct // 头结点
{
	QNode *rhead, *chead; //下边的(指针指向右)、右边的(指针指向下) 
	int m, n, k; // 行、列数 及 非零结点数 
}crossList;

void print(float a[][4], int m, int n)
{
	cout << "输出数组:" << endl;
	int i, j;
	for(i = 0; i < m; i++)
	{
		for(j = 0; j < n; j++)
		{
			cout << a[i][j] << " ";
		}
		cout << endl;
	}
	cout << endl;
}

int count(float a[][4],int m, int n)
{
	int i, j, c = 0;
	for(i = 0; i < m; i++ )
	{
		for(j = 0; j < n; j++)
		{
			if(a[i][j]!=0)
				c++;
		}
	}
	return c;
}

void creat(float a[][4], int m, int n, int k, crossList &M) // 矩阵:m x n 
{
	int i, j;
	// 初始化头结点
	if(M.chead)  
		free(M.chead);
	if(M.rhead)	
		free(M.rhead);
		
	M.m = m;
	M.n = n;
	M.k = k; 
	
	// 分配空间 并 置空 
	M.rhead = (QNode *)calloc(m, sizeof(QNode));
	M.chead = (QNode *)calloc(n, sizeof(QNode));
	
	
	//辅助链表 右边横着的 指针向下 
	QNode *temp[max];
	for(i = 0; i < n; i++)  
		temp[i] = &(M.chead[i]);
	for(i = 0; i < m; i++)
	{
		QNode *c = &(M.rhead[i]);
		for(j = 0; j < n ; j++)	
		{
			if(a[i][j]!=0)
			{
				QNode *p = (QNode *)calloc(1,sizeof(QNode));
				p->row = i;
				p->col = j;
				p->val = a[i][j];
				p->down = p->right = NULL;
				
				c->right = p;
				c = p;
				
				temp[j]->down = p;
				temp[j] = p;
			}
			
		}
	}
	cout << "十字链表创建成功!" << endl << endl;
}

void print2(crossList M)
{
	cout << "输出十字链表:" << endl;
	int i, j ,r; 
	QNode *p = (QNode* )malloc(sizeof(QNode));
	for(i = 0; i < M.m; i++)
	{	
		p = M.rhead[i].right;
		for(j = 0 ; j < M.n; j++)
		{
			if((int)p->col != j)
				cout << "0" << " ";
			else
			{
				cout << p->val << " ";
				if(p->right)
					p = p->right;
			}
		}
		cout << endl;
	}
	
}

int main()
{
	float a[4][4] = {{0,0,0,1},{0,0,3,2},{1},{0,1}};
	print(a, 4, 4);
	
	int length = count(a, 4, 4);
	crossList M;
	creat(a, 4, 4, length, M);
	print2(M);
	
	return 0;
}

3. 广义表

长度 = 最上层元素个数
深度 = 括号的最大层数

A = (),空表,长度 = 0,深度 = 1
B = (d, e),元素全是原子,长度 = 2,深度 = 1
C =(b, (c, d)),1个原子 + 1个广义表,长度 = 2,深度 = 2
D = (B, C),2个广义表,长度 = 2,深度 = 3
E = (a, E),1个原子 + 它本身,长度2,深度无穷

头尾链表:(原子结点 + 广义表结点)
原子结点 = 标记域 + 数据域
广义表结点 = 标记域 + 头指针域 + 尾指针域

扩展线性表:(原子结点 + 广义表结点)
原子结点 = 标记域 + 数据域 + 尾指针
广义表结点 = 标记域 + 头指针域 + 尾指针域

表头(Head),表尾(Tail)
取表头 不叫括号
取表尾 加括号

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_1403034144

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值