数据结构复习前言以及时间复杂度与空间复杂度

我们学会了一门语言(c语言),有了可以写程序的工具了,那么我们开始写程序,首先写程序的目的是为了解决生活中多次重复的问题以及庞大的问题,例如排队叫号问题,如果没有叫号的机器 ,只能服务员手写谁先到这里排队,还要扯着嗓子大喊到哪个号码用餐了,如果有了程序我们就可以用队列实现一个叫号机,遵循先进先出的规则是队列的要求。但是我们怎样写出这样的程序呢?

我们需要将实际生活中的问题抽象化为数据之间的问题,例如排队问题中每个人都可以看作一个数据元素,数据元素之间的关系就是先进先出,我们抽象化完成后就要将数据存储到内存中,那么采用什么存储结构呢?

首先介绍几个概念:

数据:数据是信息的载体,是描述客观事物属性的数、字符以及所有能输入到计算机中并被计算机程序识别和处理的符号的集合。

数据元素:数据元素是数据的基本单位,通常作为一个整体考虑,一个数据元素可由若干数据项组成,数据项是构成数据元素的不可分割的最小单元。

数据类型:原子类型(其值不可再分的数据类型)

结构类型(其值可以再分解为若干成分的数据类型)

抽象数据类型(ADT,我们可以用抽象数据类型定义一个完整的数据结构,包括数据对象、数据关系、基本操作集)

数据结构:是指相互之间存在一种或多种特定关系的数据元素的集合。因为在任何问题中,数据元素都不是单独出现的,它们之间有某种关系,这种数据元素只讲相互的关系称为结构。每一个数据结构都包括三部分:逻辑结构、存储结构以及数据的运算。

实际问题抽象化为逻辑结构后有这么几种类型:线性结构(一般线性结构、受限的线性结构:栈和队列以及串、线性表的推广:数组)、非线性结构(树形结构:二叉树、一般树、图形结构:有向图、无向图以及集合)

那么每一种逻辑结构都有不同的存储结构:顺序存储、链式存储、索引存储、散列存储

我们将数据存到内存后肯定要对数据进行操作,常见的几个操作:增、删、查、改。

算法:对特定问题求解步骤的一种描述,指的是指令的有限序列(程序不一定是算法,算法必有穷)

衡量一个算法的好坏:时间复杂度和空间复杂度

时间复杂度:T(n),若我们写一个算法,算法问题规模为n,算法中指令执行的总次数就是T(n)的表达式,时间复杂度就是这个表达式中最主要的一部分(若T(n)=2*n^2+2*n),则      O(n)=n^2,意思就是程序执行的总时间与n^2成正比。时间复杂度从小到大依次为:常对幂三指

空间复杂度:和时间复杂度类似,衡量的是一个程序除了需要存储空间来存放本身所用的指令、常数、变量和输入数据外,还需要一些对数据进行操作的工作单元和存储一些为实现计算所需信息的辅助空间。(例如malloc的空间、另外开辟的数组用来辅助这个算法完成)

求时间复杂度其实很简单,我们算出执行最多的语句执行的次数即可,求空间复杂度也比较简单,我们需要搞清楚那些是提前开辟好的,哪些是后来开辟的,哪些是与算法有关的,哪些是用空间换时间来辅助算法完成的。

以及最后有两道比较好的算法题目:

消失的数字:数组nums包含从0n的所有整数,但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗?

这道题目我们有四种思路可以完成

1、异或:利用 a^a=0 和 a^0=a这两个运算规则和^满足交换律,我们可以新创建一个数组存放0-n所有整数,用一个变量保存此数组所有数字异或的结果,再用另一个变量存储原先数组所有数字异或的结果,最后两个变量异或即为最终结果(空间复杂度:O(N),时间复杂度O(N))

2、利用等差数列的求和公式:直接求出0+……+n的结果再减原先数组中所有数字相加即为最终结果(时间复杂度O(N))

3、开辟新的数组:开辟一个新的数组,下标是0-n,遍历原先的数组,遍历到1,就在新数组下标为1的元素中++,遍历到3就在新数组下标为3的元素中++,最后遍历完所有的遍历一遍新的数组,为0的就是没出现的那个数字(空间复杂度:O(N),时间复杂度:O(N))

4、排序、依次找,这个复杂度超过了O(N)

旋转数组:给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

在我们学习字符串函数时做过旋转字符,这里是旋转整数数组,都是同一种思路

有三种思路,三次逆置是最重要的

1、向右轮转就是将数组第一个元素取出放到另一个变量中保存好,然后将剩余元素向左覆盖,重复这个动作几次即可

2、三次逆置,一定要搞清楚指针指向哪里,不要指错了

3、空间换时间:新创建一个相同大小的数组,将后k个元素拿到前面,再将前面的元素拿到后面即可

做这个oj题时要注意k,k的大小可能很大,一定要取余

你可能感兴趣的:(数据结构)