当前位置: 首页 > news >正文

数据结构-数组与广义表

一、数组的定义与运算

1.1 数组的定义

    数组是一个线性数据结构,由一组具有相同数据类型的元素组成。这些元素在内存中是连续存储的,可以通过索引快速访问。数组可以是一维的(如线性数组)、二维的(如矩阵)或多维的。

1.2 数组的基本运算

数组的基本运算包括:

  1. 查找:通过索引访问数组中的元素。

  2. 插入:在数组中插入一个新元素(需要移动元素)。

  3. 删除:从数组中删除一个元素(需要移动元素)。

  4. 更新:修改数组中某个位置的元素值。

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语言实现

​
#include <stdio.h>#define MAX_SIZE 100int 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++实现

​
#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实现

​
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实现

​
# 定义数组
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语言实现

​
#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); // aGList *b = createAtom(2); // bGList *c = createAtom(3); // cGList *d = createAtom(4); // dGList *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++实现

​
#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); // aGList *b = createAtom(2); // bGList *c = createAtom(3); // cGList *d = createAtom(4); // dGList *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实现

​
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); // aGList b = createAtom(2); // bGList c = createAtom(3); // cGList d = createAtom(4); // dGList 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实现

​
class GList:def __init__(self, is_atom=False, atom=None, head=None, tail=None):self.is_atom = is_atomself.atom = atomself.head = headself.tail = taildef __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)  # ab = create_atom(2)  # bc = create_atom(3)  # cd = create_atom(4)  # dbc = 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 应用场景

数据结构适用场景
数组需要快速查找和固定大小的场景
广义表需要处理嵌套结构的场景

通过以上内容,我们详细讲解了数组和广义表的定义、存储结构、操作实现以及性能分析。希望这些内容能够帮助你更好地理解和使用这两种数据结构。

相关文章:

  • 股指期货怎么锁定利润?
  • Gobuster :dir、dns、vhost
  • 【C++】 —— 笔试刷题day_17
  • PCIE网卡驱动DMA初始化配置
  • 编程技能:调试02,设置断点与删除断点
  • macOS安装java
  • 跨平台开发选Java还是C?应用场景与性能深度对比
  • 【WPF】 在WebView2使用echart显示数据
  • 深度学习--前向传播,反向传播和计算图
  • leetcode 122. Best Time to Buy and Sell Stock II
  • wait()和sleep()
  • PCIE Link Equalizaton
  • Java基础 - 集合框架总结与实战指南
  • Gin趣讲
  • 精益数据分析(3/126):用数据驱动企业发展的深度解析
  • Arcgis经纬线标注设置(英文、刻度显示)
  • Android主流播放器功能详解
  • 16.使用豆包将docker-compose的yaml转为k8s的yaml,安装各种无状态服务
  • uniapp-商城-26-vuex 使用流程
  • Java c线程等待ab线程执行完再执行
  • 做网站的的需求文档/深圳疫情最新消息
  • 0基础学网站建设/关键词排名技巧
  • 张店学校网站建设公司/好的产品怎么推广语言
  • 大兴西红门网站建设/北京seo方法
  • 长沙做模板网站/宁德市属于哪个省份
  • 南宁国贸网站建设/域名解析ip