初学数据结构

本文介绍了数据结构的基础知识,包括数据结构的分类、数据类型和算法的时间复杂度分析。详细讲解了线性表,特别是线性表的顺序存储结构及其区别,以及树的概念,如节点分类、树的存储结构和二叉树的特性。最后探讨了如何利用二叉树提高数据操作效率,阐述了在特定情况下二叉树的优越性。

数据结构分类与类型

1.数据结构分类

在这里插入图片描述

2.数据类型

数据类型的分类类似于离散数学中的分类
在这里插入图片描述

算法

1.算法的特性

在《计算机科学导论》中我们学过,算法有着以下特性:
在这里插入图片描述

2.怎么计算效率?

事前分析估算法

我们都知道二重循环要花费的时间一定比两个一重循环花的时间久,类似于这样的判断得出的结论就是事前分析估算法

事后统计方法

通过同一计算机对不同程序所花费的时间进行对比,从而得出结论的方法就是事后统计方法

3.时间复杂度

定义

算法的时间复杂度,用来度量算法的运行时间,记作: T(n) = O(f(n))。它表示随着 输入大小n 的增大,算法执行需要的时间的增长速度可以用 f(n) 来描述。

推导大O阶的方法

1.用常数1取代运行时间中的所有加法常数。
2.再修改后的运行次数函数中,只保留高阶项。
3.如果最高阶存在且不是1,则去除于这个项目相乘的常数。

分类

在这里插入图片描述

常数阶

简单来说,当一个函数中所执行的次数是在编程时确定的。则它们的时间复杂度都是O[1].

对数阶
int s=1;
while(s<n){
	s*=2;
}

在每一次循环结束后,s都更接近n,这样的就是对数阶,时间复杂度为O[logn]。

线性阶
for(i=1;i<=n;i++){
	...;
}

像这样的循环就是线性阶,它的时间复杂度为O[n].

平方阶
for(i=1;i<=n;i++){
	for(j=1;j<=n;j++)
		...;
}

类似于线性阶,双重循环就是平方阶。它的时间复杂度为O[n^2]。

指数阶

通过上面两个例子可以推导出,如果有i重循环。

for(i=1;i<=n;i++)
	for(j=1;j<=n;j++)
		for()
			for()
				...   //共有i重for循环

指数阶的时间复杂度为O[n^i]。

4.空间复杂度

定义

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。比如直接插入排序的时间复杂度是O(n^2),空间复杂度是O(1) 。而一般的递归算法就要有O(n)的空间复杂度了,因为每次递归都要存储返回信息。一个算法的优劣主要从算法的执行时间和所需要占用的存储空间两个方面衡量。

线性表

线性表是最基本、最简单、也是最常用的一种数据结构。线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的。我们说“线性”和“非线性”,只在逻辑层次上讨论,而不考虑存储层次,所以双向链表和循环链表依旧是线性表。在数据结构逻辑层次上细分,线性表可分为一般线性表和受限线性表。一般线性表也就是我们通常所说的“线性表”,可以自由的删除或添加结点。受限线性表主要包括栈和队列,受限表示对结点的操作受限制。线性表的逻辑结构简单,便于实现和操作。因此,线性表这种数据结构在实际应用中是广泛采用的一种数据结构。

1.线性表的抽象数据类型

(1)抽象数据类型:是指一个数学模型以及定义在该模型上的一组操作。抽象数据类型的定义仅取决于它的一组逻辑特征,而与其在计算机内部如何表示于实现无关,即不论其内部结构如何变化,只要他的数学特性不变,都不影响其他外部的使用。 (2)抽象数据类型的表示与实现:它可通过固有数据类型来表示和实现。即利用处理器已存的数据类型来说明新的结构,用已经实现的操作来组合新的操作。 (3)以线性表为例,这两者的关系:抽象数据类型线性表的定义仅仅是一个抽象在逻辑顺序的线性表,尚未涉及到它的存储结构,而表示便是确立该线性表的存储结构,实现便是通过一些具体的某种程序语言写出具体的算法,在通过算法得出结果。可以总结来说,它们的关系便是由抽象的逻辑顺序到具体实现算法的一个过程。

线性表的顺序存储结构

定义

顺序存储结构是存储结构类型中的一种,该结构是把逻辑上相邻的结点存储在物理位置上相邻的存储单元中,结点之间的逻辑关系由存储单元的邻接关系来体现。

存储方式

每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。但顺序存储方法的主要缺点是不便于修改,对结点的插入、删除运算时,可能要移动一系列的结点

数据长度与线性表长度的区别

数组的长度表示存放线性表的存储空间的长度,一般是分配之后固定的。
线性表的长度可以理解为数组中存放的数据的长度。是线性表中存放数据元素的个数,这个值是可以变化的 随着线性表的增,删操作量会变化注:线性表的长度不能超过数组的长度

1.树的定义

树是n(n≥0)个有限数据元素的集合。当n=0 时,称这棵树为空树。在一棵非树T 中:(1)有一个特殊的数据元素称为树的根结点,根结点没有前驱结点。(2)若n>1,除根结点之外的其余数据元素被分成m(m>0)个互不相交的集合T1,T2,…,Tm,其中每一个集合Ti(1≤i≤m)本身又是一棵树。树T1,T2,…,Tm 称为这个根结点的子树。

节点分类

(1)树的节点:一个数据元素及指向其子树的分支,结点拥有子树的数成为结点的度。
(2)叶子结点:度为0的结点
(3)非终端结点:度不为0的结点。

结点之间的关系

(1)孩子和双亲:结点的子树的根,相应的,该结点称为孩子的双亲。
(2)兄弟:同一个双亲的孩子之间互称兄弟。
(3)结点的祖先:从根结点到该结点所经过分支上的所有结点。
(4)子孙:以某结点为根的子树中的任一结点都称为该节点的子孙。
(5)无序树和有序树:如果将树中结点的各子树看成从左至右是有次序的,不能互换的,则称该数为有序树,否则为无序树。
(6)森林(fores):m(m>=0)棵互不相较的树的集合。

2.树的存储结构

双亲表示法
定义

假设以一组连续空间存储数的结点,同时在每个结点中,附设一个指示器指示其双亲结点到链表中的位置。

特点

由于根结点是没有双亲的,约定根结点的位置位置域为-1。根据结点的parent指针很容易找到它的双亲结点。所用时间复杂度为O(1),直到parent为-1时,表示找到了树结点的根。缺点:如果要找到孩子结点,需要遍历整个结构才行。

孩子表示法
定义

把每个结点的孩子结点排列起来,以单链表作为存储结构,则n个结点有n个孩子链表,如果是叶子结点则此单链表为空。然后n个头指针又组成一个线性表,采用顺序存储结构,存放进一个一维数组中。

特点

孩子表示法有两种结点结构:孩子链表的孩子结点和表头数组的表头结点

孩子兄弟表示法
定义

任意一棵树,它的结点的第一个孩子如果存在就是唯一的,它的右兄弟存在也是唯一的。因此,设置两个指针,分别指向该结点的第一个孩子和此结点的右兄弟。

3.二叉树

定义

在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”和“右子树”。二叉树常被用于实现二叉查找树和二叉堆。

特点

(1)没个节点最多有两棵子树
(2)左子树和右子树是有顺序的,次序不能任意颠倒
(3)即使只有一颗子树,也要区分左子树还是有字数

特殊二叉树

(1)完全二叉树——若设二叉树的高度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第h层有叶子结点,并且叶子结点都是从左到右依次排布,这就是完全二叉树。
(2)满二叉树——除了叶结点外每一个结点都有左右子叶且叶子结点都处在最底层的二叉树。

性质

(1) 在非空二叉树中,第i层的结点总数不超过, i>=1;
(2) 深度为h的二叉树最多有个结点(h>=1),最少有h个结点;
(3) 对于任意一棵二叉树,如果其叶结点数为N0,而度数为2的结点总数为N2,则N0=N2+1;
(4) 具有n个结点的完全二叉树的深度为(注:[ ]表示向下取整)
(5)给定N个结点,能构成h(N)种不同的二叉树。
(6)设有i个枝点,I为所有枝点的道路长度总和,J为叶的道路长度总和J=I+2i

遍历二叉树

下面有一个二叉树,这个二叉树非常特殊。因为它每一片叶子上的数值与叶子的深度正相关(即上面的永远小于下面的,左右无关),这样的树我们称为堆。我们把这一堆值放入数组里:a[15]={1,2,3,4,5,6,7,8,9...}现在我们有一个新的叶子20现在我们要删除最小的叶片,并插入这个新叶片,再找最小的叶片。
但对于数组,接下来就不好操作了,一般的方法是把新叶片放入原本1所i在的位置,再遍历一遍找到最小的数。这里我们有15次循环才能结束。
但如果用二叉树就可以走捷径。
在这里插入图片描述

怎么用二叉树走捷径?

还是这张图,我们先把1去掉并把20放入:
在这里插入图片描述

20与下面较小的2作比较发现2更小,交换202
在这里插入图片描述
其实到这里就已经结束了,但为了保证这还是一个堆,我们继续比较下面较小的,经过几次操作我们得到了最终结果:
在这里插入图片描述
这样明显比之前的方法简单而且清楚。
首先构造这个堆并,输入要替换的数:

int i=0,num;
	do{
		n++;
		i++;
		scanf("%d",&a[i]);
	}while(a[i]!=-1);
	scanf("%d",&num);
	a[1]=num;

之后将这个数一个一个向下比较:

int t,flag=0;
	while(i*2<=n&&flag==0){
		if(a[i]>a[i*2])
			t=i*2;
		else
			t=i;
		if(i*2+1<=n){
			if(a[t]>a[i*2+1])
				t=i*2+1;
		}
		if(t!=i){
			swap(t,i);
			i=t;
		}
		else
			flag=1;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值