数据结构概述与时间复杂度分析

Posted 橘猫吃不胖~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构概述与时间复杂度分析相关的知识,希望对你有一定的参考价值。

数据结构概述

1 基本概念

数据:是信息的载体,它能够被计算机识别、存储和加工处理。

数据元素:是数据的基本单位。有时一个数据元素包括若干个数据项。

数据结构:指的是数据之间的相互关系,它一般包括以下三个方面的内容:

  1. 数据的逻辑结构:数据元素之间的逻辑关系。
  2. 数据的存储结构:数据元素及其关系在计算机存储器内的表示。
  3. 数据的运算:对数据施加的操作。

数据的逻辑结构:是从逻辑关系上描述数据,它与数据的存储无关,是独立于计算机的。它有两大类:

  1. 线性结构:若结构是非空集,则有且仅有一个开始节点和一个终端节点,并且所有节点都最多只有一个直接前驱和一个直接后继。例如,线性表、数组。
  2. 非线性结构:一个节点可能有多个直接前驱和直接后继。例如,树和图。

数据的存储结构:指在存储空间中使用一个存储节点来存储一个数据元素;在存储空间中建立各存储节点之间的关联来表示数据元素之间的逻辑关系。其中存储节点是指一个数据元素在存储结构中的存储。有4种基本方式

  1. 顺序存储:每个存储节点只含有一个数据元素。所有的存储节点相继存储在一个连续的存储区里。用存储节点间的位置关系表示数据元素之间的逻辑关系。
  2. 链式存储:每个存储节点不仅包含一个数据元素,还包括指针。每个指针指向一个与本节点有逻辑关系的节点,即用指针表示逻辑关系。
  3. 索引存储:每个存储节点仅包含一个数据元素,所有的存储节点都连续存放。此外,增设一个索引表。
  4. 散列存储:每个存储节点仅包含一个数据元素,数据元素按散列(Hash)函数确定存储位置。

数据的运算:对数据施加的操作。是通过算法描述的。算法首先考虑正确性,还要考虑执行算法所耗费的时间和存储空间,同时算法要易于理解、编码、调试等。常用的运算如下:

  1. 查找运算:从结构中找出满足某种条件的节点的位置。
  2. 读取运算:读出结构中指定位置的内容。
  3. 插入运算:在结构中的某个位置上增加一个新节点。
  4. 更新运算:修改结构中某个指定节点的内容。

算法分析:包括从时间和空间方面对算法进行特性分析,从时间方面的分析称为时间复杂度;从空间方面的分析称为空间复杂度

  1. 时间复杂度:运行算法所需要的时间
  2. 空间复杂度:运行算法所需要的存储空间

时间复杂度从好到坏的级别依次是:常量阶 O(1) —> 对数阶O(log2n) —> 线性阶O(n) —> 平方阶O(n2) —> 指数阶O(2n)

2 例题分析

示例:求下面算法的时间复杂度

#include<stdio.h>
int main() 
	int s=0;
	int n=5;
	int i,j,k;
	for(i=1; i<=n; i++)  // 执行n次,循环结束s=n^3
		for(j=1; j<=n; j++)  // 执行n次,循环结束s=n^2
			for(k=1; k<=n; k++)  // 执行n次,循环结束s=5
				s++;
			
		
	
	printf("s=%d\\n",s); // 125

时间复杂度主要是查看循环的次数,在本例中,最内层循环执行n次;第二层循环也执行n次,但是每一次循环都要执行最内层循环n次,因此第二层循环一共执行n2次;最外层循环同样也执行n次,每一次循环都要执行第二层循环n次,因此本例中循环一共要执行n3次,所以最后的结果为53=125,时间复杂度为O(n3)。


示例:设A是一个线性表(a1,a2,a3,…,an),采用顺序存储结构,则在等概率的前提下,平均插入一个元素需要移动的元素个数是多少?

答: A=(a1,a2,…,an),有n+1个位置可插入元素,即a1之前,a1与a2之间,…,a(n-1)与an之间和an之后;在a1之前插入需移动n个元素、在a1与a2之间插入需移动n-1个元素、在a2与a3之间插入需移动n-2个元素……在a(n-1)与an之间插入需移动1个元素,在an之后插入需移动0个元素,那么平均插入一个元素需要移动的元素个数为:


示例:分析order函数的时间复杂度

int a[]= 2,5,1,7,9,3,6,8;
order(int j,int m) 
	int i,temp;
	if(j<m) 
		for(i=j; j<=m; i++) 
			if(a[i]<a[j]) 
				temp=a[i];
				a[i]=a[j];
				a[j]=temp;
			
			j++;
			order(j,m); // 递归调用 
		
	

void main() 
	int i;
	order(0,7);
	for(i=0; i<=7; i++) 
		printf("%4d",a[i]);
	
	printf("\\n");

在该程序中,首先为order函数传入了两个参数0和7,指定该函数,其中for循环中在第12行代码再次调用了自己,相当于再执行了for循环,外层循环一共执行m次,内层循环也执行m次,因此一共要执行m2次,因此时间复杂度为O(n2)。


示例:分析以下程序的时间复杂度

#include<stdio.h>
int main() 
	int i=1,n=8;
	while(i<=n) 
		i=i*2;
	
	printf("i=%d",i); // 16

本例中,循环体中是i=i*2,每循环一次,i的值增加一倍,因此一共执行4次,即时间复杂度为O(log2n)。

以上是关于数据结构概述与时间复杂度分析的主要内容,如果未能解决你的问题,请参考以下文章

双向链表的原理与实现

数据结构与算法分析绪论

java算法与数据结构必备知识点汇总

第二章学习小结

算法概述-第一节:算法基本概念和算法复杂性分析

数据结构 设计算法实现矩阵的相加,并分析该算法的时间复杂度