【数据结构】预备知识(数据的逻辑结构、物理结构、算法的时间复杂度、空间复杂度、相关例题)

一、程序设计 = 数据结构 + 算法

在这里插入图片描述

二、数据结构

数据结构就是存在的一种或多种特定关系的数据元素的集合。

1.逻辑结构

逻辑结构:数据对象中数据元素之间的相互关系。

四大逻辑结构

  1. 集合结构
    在这里插入图片描述

  1. 线性结构
    在这里插入图片描述

  1. 树形结构
    在这里插入图片描述

  1. 图形结构
    在这里插入图片描述

2.物理结构

物理结构:数据的逻辑结构在计算机中的存储形式。

数据元素的两种存储结构(物理结构)

  1. 顺序存储
    把数据元素存放在地址连续的存储单元里,其数据间的逻辑关系和物理关系是一致的。
  2. 链式存储
    把数据元素存放在任意的存储单元里,这组存储单元可以是连续的,也可以是不连续的。很显然这样的存储关系并不能反映其逻辑关系,因此需要指针存放与其相关联的数据元素的地址。

3.如何规范的使用数据结构

  1. 单独定义数据结构(结构体)
  2. 定义一些维护数据结构的接口(增、删、查、改等),使用时调用接口即可。
  3. 规范接口的命名风格(仿照STL):初始化init;尾插尾删pushback,popback;头插头删pushfront,popfront;中间插入删除insert,erase;创建和销毁creat,destroy;等等
  4. 动态内存的越界问题一般在释放内存时才会报错。

三、算法

1.大O渐进表示法(大O阶)

在这里插入图片描述


2.时间复杂度

算法中基本操作的执行次数,为算法的时间复杂度(不是算法执行所需的时间)

实例一:O(M+N)

在这里插入图片描述


实例二:O(1)

在这里插入图片描述


实例三:最坏情况

在这里插入图片描述

当一个算法随着输入不同时间复杂度也不同,时间复杂度做悲观的预期,看最坏的情况。所以函数strchr的时间复杂度为 O(N)


实例四:冒泡排序

//冒泡排序
void BubbleSort(int *arr, int n){

	int i = 0;
	int j = 0;
	int tmp = 0;
	
	for ( i = n - 1; i > 0; i--)
	{
		bool exchange = false;
		for ( j = 0; j < i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				exchange = true;
			}
		}
		if (!exchange)
		{
			return;
		}
	}
}

冒泡排序的时间复杂度:O(n^2)
在这里插入图片描述


实例五:二分查找法(折半查找法)

//二分查找法
int BinarySearch(int *a, int arrsize, int k){

	int left = 0;
	int right = arrsize-1;
	
	while (left <= right)
	{
		int mid = (right + left) / 2;
		if (k < a[mid])
		{
			right = mid-1;
		}
		else if (k > a[mid])
		{
			left = mid+1;
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

二分查找法的时间复杂度:O(logN)
在这里插入图片描述


实例六:递归法求斐波那契数

//递归法求斐波那契数
int Fib(int k){
	if (k < 3)
	{
		return 1;
	}
	else
	{
		return Fib(k - 1) + Fib(k - 2);
	}
}

递归法求斐波那契数的时间复杂度:O(2^N)
在这里插入图片描述


3.空间复杂度

空间复杂度算的是算法运行额外需要的变量的个数(不是额外需要的字节数)

实例一:冒泡排序

在这里插入图片描述


实例二:递归法求斐波那契数

在这里插入图片描述

  • 空间是可以重复利用,不累计的(函数执行完毕释放栈帧,循环中的变量出作用域被销毁)
  • 递归函数的空间复杂度=递归调用的层数 * 每次递归需要的额外变量个数
  • 时间是一去不复返,累计的
  • 递归函数的时间复杂度=递归调用的次数 * 每次递归的执行次数

4.常见复杂度的对比

在这里插入图片描述


5.相关例题

例题一:消失的数字
在这里插入图片描述

//消失的数字
int func(int* arr, int arrsize){
	int i = 0;
	int num = 0;
	
	for (i = 0; i < arrsize; i++)
	{
		num ^= i;
		num ^= arr[i];
	}
	num ^= arrsize;
	return num;
}

例题二:旋转字符串
在这里插入图片描述
在这里插入图片描述

int main(){
//旋转数组	
	int arr2[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
	int k = 3;
	int arrsize = sizeof(arr2) / sizeof(arr2[0]);

	printf("before:\n");
	for (int i = 0; i < arrsize; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n");

	k = k % arrsize;
	Reverse(arr2, 0, arrsize - 1 - k);
	Reverse(arr2, arrsize - k, arrsize - 1);
	Reverse(arr2, 0, arrsize - 1);

	printf("after:\n");
	for (int i = 0; i < arrsize; i++)
	{
		printf("%d ", arr2[i]);
	}
	printf("\n\n");

	system("pause");
	return 0;
}

void Reverse(int* arr, int left, int right){

	int tmp = 0;

	while (left < right)
	{
		tmp = arr[left];
		arr[left] = arr[right];
		arr[right] = tmp;
		left++;
		right--;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芥末虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值