数据结构概述
基本概念和术语
数据结构就是指数据之间的关系
(1) 数据:数据是对客观事物的符号表示,在计算机科学中是指所有能输入到计算机中并被计算机程序处理的符号的总称。
(2) 数据对象:是性质相同的数据元素的集合,是数据的一个子集。
(3) 数据元素:是数据的基本单位,在计算机程序中通常作为一个整体进行考虑和处理。一个数据元素可以由若干个数据项组成。
(4) 数据项:是数据处理中的最小单位。
逻辑结构与物理结构
(1) 数据结构:由逻辑结构和物理结构组成
- 逻辑结构:反映数据元素之间的逻辑数学关系,并不依赖于计算机。
- 物理结构(存储结构):是数据在计算机存储器中的表示,包括数据的存储方式及数据之间的逻辑关系。数据的物理结构是依赖于计算机的。
(2) 逻辑结构:四种逻辑结构
- 集合: 元素之间完全独立,无任何关联,仅属于同一集合。
c
#include <stdio.h>
// 集合:元素之间无任何逻辑关系
int main()
{
// 集合
int set[] = {10, 20, 30, 40};
int len = sizeof(set) / sizeof(set[0]);
printf("len=%d\n", len);
printf("集合结构:{");
for (int i = 0; i < len; i++)
{
printf("item=%d ", set[i]);
}
printf("}\n ");
return 0;
}
text
// 伪代码
结构 集合
元素数组 set[长度]
算法 初始化集合()
data[0] <- 10
data[1] <- 20
data[2] <- 30
data[3] <- 40
算法 遍历集合()
输出 "{"
对于每个元素 in data
输出 元素
输出 "}"
- 线性:元素之间前后有序,一对一相邻。(如顺序表,链表,栈,队列)
c
#include <stdio.h>
#define MAXSIZE 100
// 线性结构:顺序表
typedef struct
{
// 数据元素存储区
int data[MAXSIZE];
// 当前元素个数
int length;
} SeqList;
int main()
{
SeqList L;
// 初始化长度为0
L.length = 0;
// 添加元素(一对一线性关系)
L.data[0] = 10;
L.data[1] = 20;
L.data[2] = 30;
L.length = 3;
printf("线性结构-顺序表:");
for (int i = 0; i < L.length; i++)
{
printf("%d ", L.data[i]);
}
return 0;
}
text
// 伪代码
结构 顺序表
数据数组 data[最大长度]
实际长度 length
算法 初始化顺序表(L)
L.length <- 0
算法 插入元素(L, i, 值)
如何 i 合法
将 L.data[i] 赋值为 值
L.length <- L.length + 1
算法 遍历顺序表(L)
对于j从0到L.lenth-1
输出 L.data[j]
c
// 线性结构:单链表
#include <stdio.h>
#include <stdlib.h>
// 链表节点:每一个节点只指向下一个节点(一对一)
typedef struct Node
{
// 数据域
int data;
// 指针域:指向下一个节点
struct Node *next;
} Node, *LinkList;
int main()
{
// 创建头节点
LinkList head = (LinkList)malloc(sizeof(Node));
head->next = NULL;
// 创建节点1
LinkList n1 = (LinkList)malloc(sizeof(Node));
n1->data = 10;
n1->next = NULL;
// 建立一对一关系
head->next = n1;
// 创建节点2
LinkList n2 = (LinkList)malloc(sizeof(Node));
n2->data = 20;
n2->next = NULL;
// 建立一对一关系
n1->next = n2;
printf("\n线性结构-单链表:");
LinkList p = head->next;
while (p)
{
printf("%d ", p->data);
p = p->next;
}
return 0;
}
text
// 单链表伪代码
结构 节点
数据 data
指针 next 指向下一个节点
算法 创建单链表()
head <- 新建节点
head.next <- null
算法 插入节点(前驱节点,值)
新节点 <- 新建节点
新节点.data <- 值
新节点.next <- null
前驱节点.next <- 新节点
算法 遍历链表(head)
p<- head.next
当 p 不等于 null 时
输出 p.data
p <- p.next
- 树形:一个根节点对应多个子节点,层级关系。(如二叉树,普通树)
c
#include <stdio.h>
#include <stdlib.h>
// 二叉树节点:一对多关系(1个父节点-》最多2个子节点)
typedef struct TreeNode
{
// 数据
int data;
// 左子节点
struct TreeNode *lchild;
// 右子节点
struct TreeNode *rchild;
} TreeNode, *Tree;
TreeNode *createNode(int data)
{
TreeNode *node = (TreeNode *)malloc(sizeof(TreeNode));
node->data = data;
node->lchild = NULL;
node->rchild = NULL;
return node;
}
int main()
{
// 根节点
Tree root = createNode(1);
// 左节点
root->lchild = createNode(2);
// 右节点
root->rchild = createNode(3);
printf("\n树形结构-二叉树:根=%d,左孩子=%d,右孩子=%d\n",
root->data, root->lchild->data, root->rchild->data);
return 0;
}
text
// 伪代码
结构 树节点
数据 data
左节点指针 lchild
右节点指针 rchild
算法 创建节点(值)
节点 <- 新节点
节点.data <- 值
节点.lchild <- null
节点.rchild <- null
返回节点
算法 构建二叉树()
根节点 <- 创建节点(1)
根节点.lchild <- 创建节点(2)
根节点.rchild <- 创建节点(3)
输出 根,左节点,右节点的值
- 图形:任意两个节点都可能相连,无层级,无顺序。
c
#include <stdio.h>
#define N 3
int main()
{
// 顶点数据
char vertex[] = {'A', 'B', 'C'};
// 邻接矩阵:1=相连,0=不相连(多对多关系)
int edge[N][N] = {
{0, 1, 1},
{1, 0, 0},
{1, 0, 0}};
printf("图形结构-邻接矩阵:\n");
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
printf("%d", edge[i][j]);
}
printf("\n");
}
}
text
结构 图
订单数组 vertex[顶点数]
邻接矩阵 edge[顶点数][顶点数]
算法 初始化图()
vertex[0] <- 'A'
vertex[1] <- 'B'
vertex[2] <- 'C'
// 1=相连,0=不相连
edge[0][1] <- 1
edge[0][2] <- 1
edge[1][0] <- 1
edge[2][0] <- 1
算法 输出图()
对于 i 从 0 到 n-1
对于 j 从 0 到 n-1
输出 edge[i][j]
换行
(3)物理结构(存储结构):两种常用的存储结构
- 顺序存储结构:数据元素在物理内存上连续存放。
- 链式存储结构:数据在内存中不连续存放,每个节点包含 数据 + 指针,用指针把分散的节点串起来。