数据结构学习整理

一、相关概念

数据结构是相互之间存在一种或多种特定关系的数据的集合。

1、抽象层-逻辑结构

数据元素之间的逻辑关系称为数据的逻辑结构。数据的逻辑结构可以看作是从具体问题抽象出来的数学模型,它与数据的存储无关。

1.1、集合结构(集)

结构中的数据元素除了同属于一个集合外没有其他关系。

1.2、线性结构(表)

结构中的数据元素具有一对一的前后关系。

1.3、树型结构(树)

结构中的数据元素具有一对多的父子关系。

1.4、网状结构(图)

结构中的数据元素具有多对多的交叉映射关系。

2、结构层-物理结构

数据结构在计算机中的表示(又称映像)称为数据的物理结构,或称存储结构。它所研究的是数据结构在计算机中的实现方法,包括数据结构中元素的表示及元素间关系的表示。

2.1、顺序结构

结构中的数据元素存放在一段连续的地址空间中。
随机访问方便,空间利用率低,插入删除不方便。

2.2、链式结构

结构中的数据元素存放在彼此独立的地址空间中。
每个独立的地址空间称为节点。
节点除保存数据外,还需要保存相关节点的地址。
插入删除方便,空间利用率高,随机访问不方便。

2.3、索引结构

索引存储结构是用结点的索引号来确定结点存储地址,其优点是检索速度快,缺点是增加了附加的索引表,会占用较多的存储空间。

2.4、散列结构

散列存储结构是根据结点的值确定它的存储地址,优点是检索、增加和删除结点的操作速度快,缺点是采用不好的散列函数时可能出现结点单元的碰撞,而需要附加时间和空间开销。

3、实现层-运算结构

3.1、创建与销毁

分配资源,建立结构,释放资源。

3.2、插入与删除

增加、减少数据元素。

3.3、获取与修改

遍历、迭代、随机访问。

3.4、排序与查找

主要针对各种算法应用。

二、常用数据结构

1、栈

栈是一种后进先出(LIFO)的线性数据结构。
说明: 栈上的INSERT操作称为压入(PUSH),而无元素参数的DELETE操作称为弹出(POP),这两个名称使人联想到现实中的栈,比如餐馆里装有弹簧的摞盘子的栈,盘子从栈中弹出的次序刚好同它们压入的次序相反,这是因为只有最上面的盘子才能被取下来。
判空:

1
2
3
4
5
STACK-EMPTY(S)
if S.top == 0
return TRUE
else
return FALSE

压入:

1
2
3
PUSH(S, x)
S.top = S.top + 1;
S[S.top] = x;

弹出:

1
2
3
4
5
6
POP(S)
if STACK-EMPTY(S)
error "underflow"
else
S.top = S.top - 1
return S[S.top + 1]

2、队列

队列是一种先进先出(FIFO)的线性数据结构。
说明: 队列上的INSERT操作被称为入队(ENQUEUE),DELETE操作被称为出队(DEQUEUE),正如栈的POP操作一样,DEQUEUE操作也没有元素参数,队列的先进先出特性类似于收银台前排队等待结账的一排顾客。队列有队头(head)和队尾(tail),当有一个元素入队时,它被放在队尾的位置,就像一个新到来的顾客排在队伍末端一样,而出队的元素则总是在队头的那个,就像排在队伍前面等待最久的那个顾客一样。
入队:

1
2
3
4
5
6
ENQUEUE(Q, x)
Q[Q.tail] = x
if Q.tail == Q.lenght
Q.tail = 1;
else
Q.tail = Q.tail + 1

出队:

1
2
3
4
5
6
7
DEQUEUE(Q)
x = Q[Q.head]
if Q.head = Q.lenght
Q.head = 1
else
Q.head = Q.head + 1
return x

3、链表

链表是一种这样的数据结构,其中的各对象按线性顺序排列,数组的线性顺序是由数组下标决定的,然而与数组不同的是,链表的顺序是由各个对象里的指针决定的。
说明: 链表有单链表、双向链表及循环链表,其中双向链表L的每个元素都是一个对象,每个对象有一个关键字key和两个指针:next和prev。对象中还可以包含其他的辅助数据(或称卫星数据)。设x为链表的一个元素,x.next指向它在链表中的后继元素,x.prev则指向它的前驱元素。如果x.prev=NIL,则元素x没有前驱,因此是链表的第一个元素,即链表的头(head)。如果x.next=NIL,则元素x没有后继,因此是链表的最后一个元素,即链表的尾(tail)。属性L.head指向链表的第一个元素,如果L.head=NIL,则链表为空。如果一个链表是单链接的,则省略每个元素中的prev指针。如果一个链表是循环链接的,则表头元素的prev指针指向表尾元素,而表尾元素的next指针则指向表头元素。如果链表是已排序的,则链表的线性顺序与链表元素中关键字的线性顺序一样,据此,最小的元素就是表头元素,而最大的元素则是表尾元素。如果链表是未排序的,则各元素可以以任何顺序出现。
以下操作伪代码都是基于未排序的双向链表。
搜索:

1
2
3
4
5
LIST-SEARCH(L, k)
x = L.head
while x != NIL && x.key != k
x = x.next
return x

插入:

1
2
3
4
5
6
LIST-INSERT(L, x)
x.next = L.head
if L.head != NIL
L.head.prev = x
L.head = x
x.prev = NIL

删除:

1
2
3
4
5
6
7
LIST-DELETE(L, x)
if x.prev != NIL
x.prev.next = x.next
else
L.head = x.next
if x.next != NIL
x.next.prev = x.prev

4、二叉树

4.1、树的相关概念

树: 树是n个节点的集合,集合中有一个称为根的特殊节点,在根节点下分布着一些互不相交的集合,每一个集合又是一棵树,这些树称为根节点的子树。
空集合也是树,称为空树。
单个节点是一棵树,树根就是该节点本身。
若某树有多个节点,则每个节点都可以看成是根节点。
在一棵树中,有且仅有一个节点没有前驱,这个节点就是树的根节点。
除根节点外,其余每个节点有且仅有一个前驱。
每个节点可以有任意多个后继。
父节点、子节点、兄弟节点: 每个节点的子树的根称为该节点的儿子(子节点),相应的,该节点被称为子节点的父亲(父节点),具有同一父节点的节点称为兄弟节点。
节点的度: 一个节点的子树的数量称为该节点的度。
树的度: 一棵树的度是指该树中节点的最大度数。
叶节点和分支节点: 树中度为零的节点称为叶节点或终端节点,树中度不为零的节点称为分支节点或非终端节点。
节点的层数: 树是一种层次结构,每个节点都处在一定的层次上。
树的深度: 一棵树中节点的最大层数称为树的深度。
有序树和无序树: 若树种各节点的子树是按照一定次序从左向右安排的,称为有序树,否则称为无序树。
森林: 森林是m(m>=0)棵互不相交的树的集合。

4.2、二叉树的相关概念

二叉树: 一个二叉树是n个节点的集合,此集合要么是空集,要么是由一个根节点加上分别称为左子树和右子树的两个互不相交的二叉树。
二叉树的基本形态:
空:没有任何节点。
仅有根节点:只有根节点,没有子节点。
仅有左子树:只有一个子节点,且位于左子树位置,右子树位置为空。
仅有右子树:只有一个子节点,且位于右子树位置,左子树位置为空。
有左右子树:左右子树都有。
二叉树和树的两个主要差别如下:
树中节点的最大度数没有限制,而二叉树节点的最大度数为2;
树的节点无左右之分,而二叉树的节点有左右之分。
满二叉树:在二叉树中,除最下一层的叶节点外,每层的节点都有两个子节点,就构成了满二叉树。
完全二叉树:除二叉树最后一层外,其他各层的节点数都达到最大个数,且最后一层从左向右的叶节点连续存在,只缺右侧若干节点,就是完全二叉树。
二叉树的性质:
在二叉树中,第i层的节点总数最多为2i-1个。
深度为k的二叉树最多有2k-1个节点(k>=1),最少有k个节点。
对于一棵二叉树,如果其叶节点数为n0,而度为2的节点总数为n2,则n0=n2+1。
具有n个节点的完全二叉树的深度k为:k=[log2n]+1。
有n个节点的完全二叉树各节点如果用顺序方式存储,对任意节点i,有如下关系:

1
2
3
如果i!=1,则其父节点的编号为i/2;
如果2*i<=n,则其左子树根节点的编号为2*i;若2*i>n,则无左子树;
如果2*i+1<=n,则其右子树根节点的编号为2*i+1;若2*i+1>n,则无右子树。

4.3、二叉搜索树:

满足以下性质的二叉树为二叉搜索树:设x是二叉搜索树中的一个节点,如果y是x左子树种的一个节点,那么y.key<=x.key,如果y是右子树的一个节点,那么y.key>=x.key。
以下为针对搜索二叉树的基本操作伪代码介绍:
SEARCH(查找)

1
2
3
4
5
6
7
TREE-SEARCH(x, k)
if x == NIL || k == x.key
return x
if k < x.key
return TREE-SEARCH(x.left, k)
else
return TREE-SEARCH(x.right, k)

MINIMUM(最小值)

1
2
3
4
TREE-MINIMUM(x)
while x.left != NIL
x = x.left
return x

MAXIMUM(最大值)

1
2
3
4
TREE-MAXIMUM(x)
while x.right != NIL
x = x.right
return x

PREDECESSOR(前驱)

1
2
3
4
5
6
7
8
TREE-PREDECESSOR(x)
if x.left != NIL
return TREE-MAXIMUM(x)
y = x.p
while y != NIL && x == y.left
x = y
y = y.p
return y

SUCCESSOR(后继)

1
2
3
4
5
6
7
8
TREE-SUCCESSOR(x)
if x.right != NIL
return TREE-MINIMUM(x, right)
y = x.p
while y != NIL && x == y.right
x = y
y = y.p
return y

INSERT(插入)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TREE-INSERT(T, z)
y = NIL
x = T.root
while x != NIL
y = x
if z.key < x.key
x = x.left
else
x = x.right
z.p = y
if y == NIL
T.root = z
else if z.key < y.key
y.left = z
else
y.right = z

TRANSPLANT(移动)

1
2
3
4
5
6
7
8
9
TRANSPLANT(T, u, v)
if u.p == NIL
T.root = v
else if u == v.p.left
u.p.left = v
else
u.p.right = v
if v != NIL
v.p = u.p

DELETE(删除)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
TREE-DELETE(T, z)
if z.left == NIL
TRANSPLANT(T, z, z.right)
else if z.right == NIL
TRANSPLANT(T, z, z.left)
else
y = TREE-MINIMUM(z.right)
if y.p != z
TRANSPLANT(T, y, y.right)
y.right = z.right
y.right.p = y
TRANSPLANT(T, z, y)
y.left = z.left
y.left.p = y

5、图

5.1、概述:

图由数据元素和连接数据元素的线构成。在图中数据元素称为顶点(Vertex),连接这些顶点的线称为边(Edge)。一个图是由顶点集合和边集合组成,一般记为以下形式:G=(V, E)或G=(V(G), E(G)),其中,V(G)表示顶点的非空集合,每个顶点可以用不同的字母或数字来表示。E(G)是图的所有边的集合,该集合可以为空,即没有边,图的每条边由所连接的两个顶点表示。

5.2、图的相关概念:

无向图: 边没有方向的图称为无向图。
有向图: 边有方向的图称为有向图。
邻接点: 图中一条边的两个顶点互称为邻接点。
顶点的度: 图中连接某个顶点的边的数量。
完全图: 若在图中每两个顶点之间都存在一条边,则该图称为完全图。
子图: 如果一个图G2的所在顶点和边都是另一个图G1的子集,则称G2为G1的子图。
路径: 在一个图中,从顶点Vm到Vn之间存在一个顶点序列Vm、Vi1、Vi2、…、Vii、Vn,使得(Vm, Vi1)、(Vi1, Vi2)、…、(Vii, Vn),则表示从Vm到Vn有一条路径。
路径长度: 指路径上边的数量。
回路: 若路径的第一个顶点和最后一个顶点相同,称为回路。
连通图: 在无向图中,若两个顶点之间有路径,则称这两个顶点是连通的,若无向图G中任意两个顶点都是连通的,则称图G为连通图,否则称为非连通图。
连通分量: 无向图G的极大连通子图称为G的连通分量,任何连通图的连通分量只有一个,即该图本身,而非连通图就有多个连通分量。
强连通图: 若有向图G中任意两个顶点都是连通的,则称图G为强连通图。
强连通分量: 有向图G的极大强连通子图称为强连通分量。
权: 在一个图中,每条边可以标上具有某种含义的数值,该数值称为对应边的权。
网: 边上带有权值的图称为带权图,也称为网。

文章目录
  1. 1. 一、相关概念
    1. 1.1. 1、抽象层-逻辑结构
      1. 1.1.1. 1.1、集合结构(集)
      2. 1.1.2. 1.2、线性结构(表)
      3. 1.1.3. 1.3、树型结构(树)
      4. 1.1.4. 1.4、网状结构(图)
    2. 1.2. 2、结构层-物理结构
      1. 1.2.1. 2.1、顺序结构
      2. 1.2.2. 2.2、链式结构
      3. 1.2.3. 2.3、索引结构
      4. 1.2.4. 2.4、散列结构
    3. 1.3. 3、实现层-运算结构
      1. 1.3.1. 3.1、创建与销毁
      2. 1.3.2. 3.2、插入与删除
      3. 1.3.3. 3.3、获取与修改
      4. 1.3.4. 3.4、排序与查找
  2. 2. 二、常用数据结构
    1. 2.1. 1、栈
    2. 2.2. 2、队列
    3. 2.3. 3、链表
    4. 2.4. 4、二叉树
      1. 2.4.1. 4.1、树的相关概念
      2. 2.4.2. 4.2、二叉树的相关概念
      3. 2.4.3. 4.3、二叉搜索树:
    5. 2.5. 5、图
      1. 2.5.1. 5.1、概述:
      2. 2.5.2. 5.2、图的相关概念:
,