一、数组的定义与运算
1.1 数组的定义
数组是一个线性数据结构,由一组具有相同数据类型的元素组成。这些元素在内存中是连续存储的,可以通过索引快速访问。数组可以是一维的(如线性数组)、二维的(如矩阵)或多维的。
1.2 数组的基本运算
数组的基本运算包括:
-
查找 :通过索引访问数组中的元素。
-
插入:在数组中插入一个新元素(需要移动元素)。
-
删除:从数组中删除一个元素(需要移动元素)。
-
更新:修改数组中某个位置的元素值。
1.3 数组运算的图解
以下是一个简单的数组插入操作的图解:
初始数组:[1, 2, 3, 4, 5]
插入元素6到索引2的位置:
步骤1:移动索引2及之后的元素
步骤2:在索引2的位置插入6
结果数组:[1, 2, 6, 3, 4, 5]
二、数组的顺序存储与实现
2.1 数组的顺序存储
数组的顺序存储是指将数组的元素按照一定的顺序(如行优先或列优先)存储在内存中。对于多维数组,通常采用行优先存储(如C语言)或列优先存储(如Fortran)。
2.2 数组的实现
以下是数组在不同语言中的实现:
2.2.1 C语言实现
bash
#include <stdio.h>
#define MAX_SIZE 100
int main() {
int arr[MAX_SIZE] = {0}; // 定义一个数组
int n = 5; // 数组长度
int i;
// 初始化数组
for (i = 0; i < n; i++) {
arr[i] = i + 1; // 将数组元素初始化为1到5
}
// 查找数组元素
printf("数组元素: ");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 插入元素
int insertValue = 6;
int insertIndex = 2;
for (i = n; i > insertIndex; i--) {
arr[i] = arr[i - 1]; // 移动元素
}
arr[insertIndex] = insertValue; // 插入新元素
n++; // 数组长度加1
// 输出插入后的数组
printf("插入后的数组: ");
for (i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
2.2.2 C++实现
cpp
#include <iostream>
using namespace std;
int main() {
int arr[] = {1, 2, 3, 4, 5}; // 定义并初始化数组
int n = 5; // 数组长度
// 查找数组元素
cout << "数组元素: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 插入元素
int insertValue = 6;
int insertIndex = 2;
int *newArr = new int[n + 1]; // 创建新数组
for (int i = 0; i < insertIndex; i++) {
newArr[i] = arr[i]; // 复制前半部分
}
newArr[insertIndex] = insertValue; // 插入新元素
for (int i = insertIndex; i < n; i++) {
newArr[i + 1] = arr[i]; // 复制后半部分
}
delete[] arr; // 释放旧数组
arr = newArr; // 更新数组指针
n++; // 数组长度加1
// 输出插入后的数组
cout << "插入后的数组: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
cout << endl;
delete[] arr; // 释放数组
return 0;
}
2.2.3 Java实现
java
public class ArrayExample {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 4, 5}; // 定义并初始化数组
int n = 5; // 数组长度
// 查找数组元素
System.out.print("数组元素: ");
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
// 插入元素
int insertValue = 6;
int insertIndex = 2;
int[] newArr = new int[n + 1]; // 创建新数组
for (int i = 0; i < insertIndex; i++) {
newArr[i] = arr[i]; // 复制前半部分
}
newArr[insertIndex] = insertValue; // 插入新元素
for (int i = insertIndex; i < n; i++) {
newArr[i + 1] = arr[i]; // 复制后半部分
}
arr = newArr; // 更新数组引用
n++; // 数组长度加1
// 输出插入后的数组
System.out.print("插入后的数组: ");
for (int i = 0; i < n; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
}
2.2.4 Python实现
python
# 定义数组
arr = [1, 2, 3, 4, 5]
n = len(arr) # 数组长度
# 查找数组元素
print("数组元素:", arr)
# 插入元素
insert_value = 6
insert_index = 2
arr.insert(insert_index, insert_value) # 使用Python内置的insert方法
n += 1 # 数组长度加1
# 输出插入后的数组
print("插入后的数组:", arr)
三、特殊矩阵的压缩存储
3.1 规律分布的特殊矩阵
特殊矩阵是指具有某种规律分布的矩阵,如对称矩阵、三角矩阵等。这些矩阵可以通过压缩存储来节省空间。
3.1.1 对称矩阵
对称矩阵是一个方阵,其元素满足 aij=aji。对称矩阵可以压缩存储为一个一维数组,只存储上三角或下三角的元素。
3.1.2 三角矩阵
三角矩阵是一个方阵,其上三角或下三角的元素均为常数(如0)。三角矩阵也可以压缩存储为一个一维数组。
3.2 稀疏矩阵
稀疏矩阵是一个大多数元素为0的矩阵。稀疏矩阵可以通过三元组表或十字链表进行压缩存储。
3.2.1 三元组表
三元组表是一种压缩存储稀疏矩阵的方法,只存储非零元素的行号、列号和值。
3.2.2 十字链表
十字链表是一种链式存储结构,每个非零元素用一个节点表示,节点包含行指针和列指针。
3.3 稀疏矩阵的图解
以下是一个稀疏矩阵的三元组表示图解:
原始矩阵:
1 0 0 0
0 2 0 0
0 0 3 0
0 0 0 4
三元组表:
行 | 列 | 值
1 | 1 | 1
2 | 2 | 2
3 | 3 | 3
4 | 4 | 4
四、广义表
4.1 广义表的概念
广义表(Generalized List)是一种递归的数据结构,可以看作是线性表的推广。广义表中的元素可以是原子(单个数据项)或子表(另一个广义表)。
广义表的定义形式为: LS=(a1,a2,...,an) 其中,ai 可以是原子或子表。
4.2 广义表的存储结构
广义表的存储结构通常采用头尾表示法或孩子兄弟表示法。
4.2.1 头尾表示法
头尾表示法将广义表分为头部和尾部。头部可以是原子或子表,尾部是剩下的元素组成的子表。
4.2.2 孩子兄弟表示法
孩子兄弟表示法将广义表中的每个元素视为一个节点,节点包含数据域、第一个孩子的指针和下一个兄弟的指针。
4.3 广义表的操作实现
广义表的基本操作包括求表头、表尾、插入、删除等。
4.4 广义表的图解
以下是一个广义表的头尾表示法图解:
广义表:A = (a, (b, c), d)
头:a
尾:((b, c), d)
4.5 广义表的代码实现
4.5.1 C语言实现
bash
#include <stdio.h>
#include <stdlib.h>
// 定义广义表节点
typedef struct GList {
int isAtom; // 是否为原子
int atom; // 原子值
struct GList *head; // 头指针
struct GList *tail; // 尾指针
} GList;
// 创建原子节点
GList* createAtom(int value) {
GList *node = (GList*)malloc(sizeof(GList));
node->isAtom = 1;
node->atom = value;
node->head = NULL;
node->tail = NULL;
return node;
}
// 创建子表节点
GList* createSublist(GList *head, GList *tail) {
GList *node = (GList*)malloc(sizeof(GList));
node->isAtom = 0;
node->head = head;
node->tail = tail;
return node;
}
// 打印广义表
void printGList(GList *list) {
if (list == NULL) {
printf("()");
return;
}
if (list->isAtom) {
printf("(%d)", list->atom);
} else {
printf("(");
printGList(list->head);
printf(", ");
printGList(list->tail);
printf(")");
}
}
int main() {
// 创建广义表 A = (a, (b, c), d)
GList *a = createAtom(1); // a
GList *b = createAtom(2); // b
GList *c = createAtom(3); // c
GList *d = createAtom(4); // d
GList *bc = createSublist(b, createSublist(c, NULL)); // (b, c)
GList *A = createSublist(a, createSublist(bc, createSublist(d, NULL))); // (a, (b, c), d)
printf("广义表A: ");
printGList(A);
printf("\n");
return 0;
}
4.5.2 C++实现
cpp
#include <iostream>
using namespace std;
// 定义广义表节点
struct GList {
bool isAtom; // 是否为原子
int atom; // 原子值
GList *head; // 头指针
GList *tail; // 尾指针
GList() : isAtom(false), head(nullptr), tail(nullptr) {}
};
// 创建原子节点
GList* createAtom(int value) {
GList *node = new GList;
node->isAtom = true;
node->atom = value;
return node;
}
// 创建子表节点
GList* createSublist(GList *head, GList *tail) {
GList *node = new GList;
node->isAtom = false;
node->head = head;
node->tail = tail;
return node;
}
// 打印广义表
void printGList(GList *list) {
if (list == nullptr) {
cout << "()";
return;
}
if (list->isAtom) {
cout << "(" << list->atom << ")";
} else {
cout << "(";
printGList(list->head);
cout << ", ";
printGList(list->tail);
cout << ")";
}
}
int main() {
// 创建广义表 A = (a, (b, c), d)
GList *a = createAtom(1); // a
GList *b = createAtom(2); // b
GList *c = createAtom(3); // c
GList *d = createAtom(4); // d
GList *bc = createSublist(b, createSublist(c, nullptr)); // (b, c)
GList *A = createSublist(a, createSublist(bc, createSublist(d, nullptr))); // (a, (b, c), d)
cout << "广义表A: ";
printGList(A);
cout << endl;
return 0;
}
4.5.3 Java实现
java
public class GList {
private boolean isAtom; // 是否为原子
private int atom; // 原子值
private GList head; // 头指针
private GList tail; // 尾指针
// 构造函数
public GList() {
isAtom = false;
head = null;
tail = null;
}
// 创建原子节点
public static GList createAtom(int value) {
GList node = new GList();
node.isAtom = true;
node.atom = value;
return node;
}
// 创建子表节点
public static GList createSublist(GList head, GList tail) {
GList node = new GList();
node.isAtom = false;
node.head = head;
node.tail = tail;
return node;
}
// 打印广义表
public void print() {
if (this == null) {
System.out.print("()");
return;
}
if (isAtom) {
System.out.print("(" + atom + ")");
} else {
System.out.print("(");
head.print();
System.out.print(", ");
tail.print();
System.out.print(")");
}
}
public static void main(String[] args) {
// 创建广义表 A = (a, (b, c), d)
GList a = createAtom(1); // a
GList b = createAtom(2); // b
GList c = createAtom(3); // c
GList d = createAtom(4); // d
GList bc = createSublist(b, createSublist(c, null)); // (b, c)
GList A = createSublist(a, createSublist(bc, createSublist(d, null))); // (a, (b, c), d)
System.out.print("广义表A: ");
A.print();
System.out.println();
}
}
4.5.4 Python实现
python
class GList:
def __init__(self, is_atom=False, atom=None, head=None, tail=None):
self.is_atom = is_atom
self.atom = atom
self.head = head
self.tail = tail
def __str__(self):
if self.is_atom:
return f"({self.atom})"
else:
return f"({self.head}, {self.tail})"
# 创建原子节点
def create_atom(value):
return GList(is_atom=True, atom=value)
# 创建子表节点
def create_sublist(head, tail):
return GList(is_atom=False, head=head, tail=tail)
# 主函数
if __name__ == "__main__":
# 创建广义表 A = (a, (b, c), d)
a = create_atom(1) # a
b = create_atom(2) # b
c = create_atom(3) # c
d = create_atom(4) # d
bc = create_sublist(b, create_sublist(c, None)) # (b, c)
A = create_sublist(a, create_sublist(bc, create_sublist(d, None))) # (a, (b, c), d)
print("广义表A:", A)
五、总结核心知识点
5.1 时间性能分析
数据结构 | 查找 | 插入 | 删除 | 更新 |
---|---|---|---|---|
数组 | O(1) | O(n) | O(n) | O(1) |
广义表 | O(n) | O(n) | O(n) | O(n) |
5.2 空间性能分析
数据结构 | 空间复杂度 |
---|---|
数组 | O(n) |
广义表 | O(n) |
5.3 应用场景
数据结构 | 适用场景 |
---|---|
数组 | 需要快速查找和固定大小的场景 |
广义表 | 需要处理嵌套结构的场景 |
通过以上内容,我们详细讲解了数组和广义表的定义、存储结构、操作实现以及性能分析。希望这些内容能够帮助你更好地理解和使用这两种数据结构。