【ONE·C || 函数与数组】

总言

  C语言:函数、数组初步认识。


  
  

1、函数

1.1、是什么

1.1.1、基本介绍

  1)、C语言中函数的分类

库函数
自定义函数

  库函数: 早期的C语言是没有库函数的,此时由于各有各的方法实现,会带来如下问题:功能类似,但代码冗余、开发效率低、不标准。因此把一些常用的功能实现为函数,集成为库,由C语言提供。
  
  自定义函数: 由我们自己设计实现的函数,即为自定义函数,能满足我们个人需求。自定义函数和库函数一样,有函数名,返回值类型函数参数

ret_type fun_name(para1, * )
{
 statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1    函数参数
{} 函数体

  
  
  

1.1.2、库函数使用演示(strcpy、memset)

  1)、库函数strcpy使用演示
在这里插入图片描述

  演示要求:拷贝字符串,并验证结尾字符"\0"也一并拷贝了。

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[] = "abcdefg";
	char arr2[20] = "xxxxxxxxxxx";
	strcpy(arr2, arr1);

	return 0;
}

在这里插入图片描述

  
  
  2)、库函数memset使用演示
在这里插入图片描述

  演示要求:将数组前五个元素值设置为“X”

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "hello world!";
	memset(arr, 'X', 5);
	printf("%s\n", arr);
	return 0;
}

在这里插入图片描述
  
  
  

1.1.3、自定义函数使用演示

  1)、写一个函数:可以找出两个整数中的最大值

int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}


int main()
{
	int num1 = 0;
	int num2 = 0;
	scanf("%d %d",&num1,&num2);
	int max = get_max(num1, num2);
	printf("max = %d\n", max);
	return 0;
}

  
  
  2)、写一个函数:可以交换两个整形变量的内容

#include <stdio.h>
void Swap1(int x, int y)//传值
{
	int tmp = 0;
	tmp = x;
	x = y;
	y = tmp;
}
void Swap2(int* x, int* y)//传引用
{
	int tmp = 0;
	tmp = *x;
	*x = *y;
	*y = tmp;
}
int main()
{
	int num1 = 1;
	int num2 = 2;
	Swap1(num1, num2);
	printf("Swap1::num1 = %d num2 = %d\n", num1, num2);
	Swap2(&num1, &num2);
	printf("Swap2::num1 = %d num2 = %d\n", num1, num2);
	return 0;
}

在这里插入图片描述
  
  
  

1.2、函数参数、传值调用和传址调用

  1)、基本介绍

实际参数(实参):真实传给函数的参数
形式参数(形参):是指函数名后括号中的变量

  实参:
    ①可以是常量、变量、表达式、函数等。
    ②无论实参是何种类型的量,在进行函数调用时都必须有确定的值,以便把这些值传送给形参。
  
  形参:
    ①形式参数只有在函数被调用的过程中才实例化(分配内存单元)
    ②形式参数在函数调用完成之后就自动销毁。
  
  
  
  2)、传值调用和传址调用

**传值调用:**
函数的形参和实参分别占有不同内存块,对形参的修改不会影响实参。

**传址调用:**
传址调用是把函数外部创建变量的内存地址传递给函数参数的一种调用函数的方式。
这种传参方式可以让函数和函数外边的变量建立起真正的联系,也就是函数内部可以直接操作函数外部的变量。

  
  
  

1.3、相关练习

1.3.1、写一个函数:可以判断一个数是不是素数

#include<math.h>
int is_prime(int val)
{
	//试除法
	//2~n-1  \  2~sqrt(n)
	for (int i = 2; i < sqrt(val); ++i)
	{
		if(val % i == 0)//说明有别的因数
		{
			return 0;
		}
	}
	return 1;
}

int main()
{
	//任务目标:判断100~200间的素数
	for (int i = 101; i <= 200; i+=2)//首先排除偶数
	{
		if (is_prime(i) == 1)
		{
			printf("%d ", i);
		}
	}
	return 0;
}

在这里插入图片描述

  
  
  
  

1.3.2、写一个函数:判断一年是不是闰年

int is_leap_year(int year)
{
	//四年一闰,百年不闰;
	//四百年一闰;
	if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
	{
		return 1;
	}
	return 0;
}

int main()
{
	//任务目标:打印1000~2000年之间的闰年

	//产生年份
	for (int y = 1000; y <= 2000; ++y)
	{
		//判断
		if (is_leap_year(y) == 1)
		{
			printf("%d ", y);
		}
	}
	printf("\n");

	return 0;
}

在这里插入图片描述
  
  
  

1.3.3、写一个函数:实现一个整形有序数组的二分查找

int binary_search(int arr[],int key,int len)
{
	int left = 0;
	int right = len - 1;
	while (left <= right)
	{
		int mid = left + (right - left) / 2;

		if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else
		{
			return mid;

		}
	}
	return -1;
}


int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };//有序数组
	int key = 0;
	printf("输入要查找的数字:");
	scanf("%d", &key);
	int len = sizeof(arr) / sizeof(arr[1]);
	int ret=binary_search(arr, key, len);
	if (-1 == ret)
	{
		printf("找不到\n");
	}
	else {
		printf("找到了,下标为:%d\n", ret);

	}
	return 0;
}

  一个问题:binary_search能否不传递实参len,而是选择在函数体内计算int len = sizeof(arr) / sizeof(arr[1]);

binary_search(arr, key);

  回答:arr数组传参,传递的不是整个数组,而是数组首元素地址。int arr[]本质上是int* arr
  
  
  

1.3.4、写一个函数:每调用一次这个函数,就会将 num 的值增加1

void test(int* num)
{
	(*num)++;//优先级问题
}

int main()
{
	int num = 0;
	int n = 5;//调用次数
	while (n)
	{
		test(&num);//传址
		n--;
	}
	printf("%d\n", num);
	return 0;
}

在这里插入图片描述
  
  
  

1.4、函数的嵌套调用和链式访问

1.4.1、函数嵌套调用

  1)、是什么
  函数和函数之间可以根据实际的需求进行组合,也就是互相调用的。

void new_line()
{
    printf("hehe\n");
}
void three_line()
{
    int i = 0;
    for (i = 0; i < 3; i++)
    {
        new_line();
    }
}
int main()
{
    three_line();
    return 0;
}

  衍生思考:函数是否能嵌套定义?

int main()//函数一
{
    void three_line()//函数二
    {
        int i = 0;
        for (i = 0; i < 3; i++)
        {
            void new_line()//函数三
            {
                printf("hehe\n");
            }
        }
    }    
    return 0;
}

  回答:不能。
  
  

1.4.2、函数链式访问(printf返回值介绍)

  1)、是什么
  把一个函数的返回值作为另外一个函数的参数,称之为链式访问。

#include<string.h>
int main()
{
	int len = strlen("abcdef");
	printf("%d\n", len);

	printf("%d\n", strlen("abcdef"));
	return 0;
}

在这里插入图片描述
  
  
  2)、其它一些例子
  如下,以下结果是什么?

int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	return 0;
}

在这里插入图片描述
在这里插入图片描述
  
  
  
  

1.5、函数声明和定义

  函数声明:

1. 告诉编译器有一个函数叫什么,参数是什么,返回类型是什么。但是具体是不是存在,函数声明决定不了。
2. 函数的声明一般出现在函数的使用之前。要满足先声明后使用。
3. 函数的声明一般要放在头文件中的。

  
  函数定义:

函数的定义是指函数的具体实现,交待函数的功能实现。

  
  演示举例:

//函数声明
int get_max(int x, int y);
int get_max(int , int );//可以把形参名字省略


int main()
{
	int num1 = 10;
	int num2 = 20;
	int max = get_max(num1, num2);
	printf("max = %d\n", max);
	return 0;
}


//函数定义
int get_max(int x, int y)
{
	return (x > y) ? (x) : (y);
}

  
  
  

1.6、函数递归

1.6.1、概念与递归的必要条件

  1)、是什么
  说明:递归即函数调用其本身,其主要思想在于把大事化小,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。类似于一个深层的嵌套(俄罗斯套娃)。

  以下为一个演示例子:main函数自己调用其本身

//main函数自己调用自己
#include<stdio.h>
int main(void)
{
	printf("hehe\n");
	main();
	return 0;
}

在这里插入图片描述
  如上图,虽然是实现了递归,但其结果为程序终止,通过调试发现,造成程序终止的原因是栈溢出。
  
  
  2)、递归的两个使用条件
  1、递归存在限制条件,符合限制条件后,递归停止。
  2、每次递归调用,都要朝这一限制条件发展
  
  
  

1.6.2、相关练习演示

1.6.2.1、接受一个整型值(无符号),按照顺序打印它的每一位

例如:
输入:1234,输出 1 2 3 4.

  1)、假如采用非递归法,实现如下:
  要正位打印每一个数,可将其不同数位上的数一一剥离。通常来说十进制下,/10、%10能做得到。但如果直接运用,得到的则是4321逆序,所以我们可以将剥离下的每个位数先存放在数组中,再逆序打印。

int main()
{
	unsigned int num = 0;

	scanf("%u", &num);

	int digit = 0;//统计num位数
	int arr[10] = { 0 };//存储num每个位数,10为32位下无符号整型最大位数
	while (num)
	{
		arr[digit] = num % 10;
		num /= 10;
		digit++;
	}
	for (int i = digit - 1; i >= 0; i--)//倒序打印
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

  
  2)、假如采用递归,实现如下:
  在递归方式中,对于1234仍旧采用/10、%10的方法,只是我们将数字分为两部分,对末位数,将其剥离打印,对非末位数,再次调用函数剥离。故有:
  f(1234)=f(123)+4
  f(123)=f(12)+3
  f(12)=f(1)+2
  

void print(unsigned int num)
{
	if (num > 9)//说明num目前大于个位
	{
		print(num / 10);
	}
	printf("%d ",(num % 10));
}


int main()
{
	unsigned int num = 0;
	scanf("%u", &num);
	print(num);
	return 0;
}

  上述print中,if条件语句printf打印二者顺序至关重要,其决定着输出结果顺序问题。由于一上来就满足if语句,所以进入递归调用函数,直到来到终止条件时,执行printf语句,然后再层层递归返回,完成相应递归层中没有执行的函数语句。

在这里插入图片描述

  
  
  

1.6.2.2、编写函数不允许创建临时变量,求字符串的长度

  1)、使用库函数的情况如下:
  arr存储的是a、b、c、d、e、f、\0strlen求得'\0'前字符长度。

#include <stdio.h>
#include <string.h>
int main(void)
{
	char arr[] = "abcdef";
	printf("%d\n", strlen(arr));
	return 0;
}

  
  
  2)、创建临时变量的情况如下:

int mystrlen(char* arr)
{
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}
int main(void)
{
	char arr[] = "abcdef";
	printf("%d", mystrlen(arr));
	return 0;
}

  
  
  3)、不允许创建临时变量的情况如下
  f("abc")=1+f("bc")
  f("bc")=1+f("c")
  f("c")=1+f(‘\0')
  f(‘\0')=0
  既有:f("abc")=1+f("bc")=1+1+f("c")=1+1+1+f(‘\0')=3

#include <stdio.h>
int mystrlen(char* arr)
{
	if (*arr == '\0')
		return 0;
	return 1 + mystrlen(++arr);
}
int main(void)
{
	char arr[] = "abcdef";
	printf("%d", mystrlen(arr));
	return 0;
}

  
  
  

1.6.2.3、求n的阶乘(不考虑溢出)

  1)、使用非递归的方法

//非递归方式:
#include<stdio.h>
int main(void)
{
	int n;
	scanf("%d", &n);

	int sum = 1;
	while (n > 0)
	{
		sum *= n;
		n--;
	}
	return 0;
}

  
  
  2)、使用递归的方法

//用递归的方式:
int factorial(int n)
{
	if (n <= 1)
		return 1;
	else
		return n * factorial(n - 1);
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", factorial(n));
	return 0;
}

  
  
  

1.6.2.4、求第n个斐波那契数(不考虑溢出)

  1)、使用递归的方法

//以递归方式实现:
#include<stdio.h>
int fib(int n)
{
	if (n <= 2)
		return 1;
	return fib(n - 1) + fib(n - 2);
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", fib(n));
	return 0;
}

  
  
  2)、使用非递归的方法
  非递归的方法能解决此处的递归效率问题。

//以非递归的方式实现:
#include<stdio.h>
int fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;//此处为c赋值为1不影响后续计算,且能解决第一、第二个斐波那契数
	while (n - 2)//头俩项不需要计算,从第三项开始,第三项需要循环1次,第四项循环2次,以此类推,第n项循环n-2次。
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main(void)
{
	int n;
	scanf("%d", &n);
	printf("%d", fib(n));
	return 0;
}

  
  
  
  
  

2、数组

2.1、一维数组

2.1.1、一维数组创建

  1)、基本介绍
  数组:一组相同类型元素的集合。

type_t   arr_name   [const_n];
//type_t 数组的元素类型
//arr_name 数组名
//const_n 常量表达式,用来指定数组的大小

  
  2)、演示实例

  一般情况如下:

int arr1[10];

  关于数组元素大小是否能用变量的说明:
  C99标准之前,不支持使用变量,只能是常量。C99中,新增了变长数组的概念,允许数组的大小是变量,而且要求编译器支持C99标准

int count = 10;
int arr2[count];

  同样的,即使用const修饰变量后为数组定义大小,因其是常变量,也要求编译器支持C99标准。

const int count = 10;
int arr2[count];

  需要注意:

  1、const修饰的count,在C语言中属于常变量,在C++中属于常量。因此假若我们用.cpp文件来实现,在VS中是能运行成功的。

  2、变长数组不能初始化。因为元素个数的不确定性,初始化数组是无意义的。比如,变长数组中元素个数是根据scanf函数来自设的,则初始化变长数组便是无意义之事。

int count = 10;
scanf("%d",&count);
int arr2[count];

  
  

2.1.2、一维数组初始化

  数组的初始化,是指在创建数组的同时给数组的内容一些合理初始值。
  

  1)、整型数组初始化相关演示

int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };//完全初始化
	int arr2[10] = { 1,2,3,4};//不完全初始化
	return 0;
}

在这里插入图片描述
  
  假如数组不初始化,其内部放置的是随机值,根据编译器而定,有的会是0xcccccccc,有的会是0xcdcdcdcd,不唯一,局部变量同理。但要注意,全局变量不初始化时默认值为0静态变量同理

int a;//全局变量
int main()
{
	int arr3[10];//不初始化
	int b;//局部变量
	static int c;//静态变量
	printf("%d\n", a);
	printf("%d\n", c);
	return 0;
}

  原因:内存空间被划分为不同区域,对于全局变量、静态变量,其放置在静态区,默认初始化为0;对于局部变量,一些形式参数,其放置在栈区,默认不初始化时为随机值。
在这里插入图片描述

  
  2)、字符型数组初始化相关演示

int main()
{
	char ch1[] = { 'a','b','c','d' };
	char ch2[] = { 'a',98,'c','d' };//字符b的ASCII码值为98
	char ch3[] = "abcd";//'a','b','c','d','\0'
	char ch4[6]= { 'a','b','c','d' };//不完全初始化,默认0,对应ASCII为'\0'
	return 0;
}

在这里插入图片描述
  致于此处涉及的strlen相关介绍,我们在初识C语言那一章节中有讲述。

  
  
  

2.1.3、一维数组使用与存储

  1)、如何访问一维数组元素:下标引用操作符
  数组是使用下标来访问的,下标从0开始。

#include <stdio.h>
int main()
{
    int arr[10] = { 0 };//数组的不完全初始化
    int sz = sizeof(arr) / sizeof(arr[0]);//计算数组的元素个数
    int i = 0;//做下标
    for (i = 0; i < sz; i++)//遍历赋值
    {
        arr[i] = i;
    }
    for (i = 0; i < sz; ++i)//遍历打印
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

  arr[i]:需要注意的是,虽然我们说,在非C99标准下,不能使用变量来定义数组大小,但从未规定,在使用下标引用操作符访问数组时,我们不能使用变量。[ ]左操作数是数组名,右操作数是下标大小。
在这里插入图片描述

  
  
  2)、一维数组在内存中的存储

#include <stdio.h>
int main()
{
    int arr[10] = { 0 };
    int i = 0;
    int sz = sizeof(arr) / sizeof(arr[0]);

    for (i = 0; i < sz; ++i)
    {
        printf("&arr[%d] = %p\n", i, &arr[i]);
    }
    return 0;
}

在这里插入图片描述

  观察可得:
  1、一维数组在内存中连续存放。
  2、随着数组下标的增长,地址是由低到高变化的。(这样做就方便使用指针来操作)

int*p=arr;//数组首元素
p+1;//int* ,+1 得下一个元素,依此类推

  
  为什么地址间相差4的原因:
  整型元素内存大小是4字节,而一个字节有一个地址,四个字节就占据了四个地址,即用四个地址表示一个整型元素。
  
  
  
  

2.2、二维数组

2.2.1、二维数组创建与初始化

  1)、二维数组创建

//数组创建
int arr[3][4];
char arr[3][5];
double arr[2][4];

  2)、二维数组初始化

//数组初始化
int arr[3][4] = {1,2,3,4};
//1、先放行,行满跳下一列,值不够时默认为0
//2、不完全初始化,默认为0。
int arr[3][4] = {{1,2},{4,5}};
//1、若规定了行列具体元素,可用花括号分隔
int arr[][4] = {{2,3},{4,5}};
//1、二维数组如果有初始化,行可以省略,列不能省略

  对于省略行的情况,一行溢出的数组元素可以换行排列。但如果省略行列,如下述情况,数组可能为arr[1][10]arr[2][5]arr[5][2], arr[10][1],故同时省略行和列是非法的。

int arr[ ][ ] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 

  
  
  

2.2.2、二维数组的基本使用

  二维数组的使用也是通过下标的方式。[][]指定行、列。

#include <stdio.h>
int main()
{
    int arr[][4] = { {1,2,3},{2,3,4},{3,4,5},{4,5,6} };
    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < 4; ++j)
        {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述

  问题:
  类似于int arr[][4],是否能算处单独的行、列?

//行:
    int row = sizeof(arr) / sizeof(arr[0]);//整个数组大小/任意一行大小
//列:
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);//某一行整体元素大小/该行单个元素大小

在这里插入图片描述

  
  
  

2.2.3、二维数组在内存中的存储

#include <stdio.h>
int main()
{

    int arr[][4] = { {1,2,3},{2,3,4},{3,4,5},{4,5,6} };
    int row = sizeof(arr) / sizeof(arr[0]);//整个数组大小/任意一行大小
    int col = sizeof(arr[0]) / sizeof(arr[0][0]);//某一行整体元素大小/该行单个元素大小
    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
        }
        printf("\n");
    }
    return 0;
}

在这里插入图片描述
  由上述结果可知,这也是为什么二维数组初始化时行可以省略,列不能省略的原因。因为二维数组连续存放,不知道行但知道了列,也能在内存区域中划分处二维数组具体行列大小。
  
  另外,需要注意的是,对于二维数组,可以将每行视作一维数组。其数组名称为arr[0]arr[1]arr[2]arr[3]
  对每行元素的访问,相当于arr[0][j]arr[1][j]arr[2][j]arr[3][j]
  即二维数组是一维数组的数组:二维数组arr[4][4]的元素个数有有三个,每个元素都是一个一维数组(以int为类型,元素个数为4个的数组)
  
  
  
  

2.3、数组越界

  基本描述:
在这里插入图片描述
  如下述代码:

#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    int i = 0;
    for (i = 0; i <= 10; i++)
    {
        printf("%d ", arr[i]);//当i等于10的时候,越界访问了
    }
    return 0;
}

在这里插入图片描述
  需要注意的是,二维数组也存在越界。那么,二维数组越界在内存中的显示?
  由于二维数组在内存中同一维数组一样是连续排列的,而且是每行排列完后接着下一行。由此可知,若二维数组越界,对于最后一行最后元素,越界会访问到数组外的内存空间,对于数组内部,越界会访问到后续行中元素。
  
  
  

2.4、数组作为函数参数

2.4.1、数组名初步认识

  数组名是数组首元素地址。
  但有两个例外:
  1、sizeof(数组名),此时数组名表示整个数组,计算的是整个数组的大小。
  2、&数组名。此处数组名表示整个数组,取出的是整个数组的地址。

#include <stdio.h>
int main()
{
    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    printf("arr:    %p\n", arr);
    printf("arr[0]: %p\n", &arr[0]);
    printf("&arr:   %p\n", &arr);

    printf("\nsizeof(arr):%d\n\n",sizeof(arr));

    printf("arr:    %p\n", arr+1);
    printf("arr[0]: %p\n", &arr[0]+1);
    printf("&arr:   %p\n", &arr+1);

    return 0;
}

在这里插入图片描述

  
  
  
  

2.4.2、冒泡排序设计1.0

  冒泡排序(Bubble Sort) 是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。 遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
  
在这里插入图片描述
  
  冒泡排序的基本步骤是:
  1、从第一个元素开始,比较相邻的两个元素。根据排序需求(升序、降序),选择是否交换它们。(例如排升序,若比较的两个元素中,前一个比后一个大,则交换它们)。
  2、用这个元素再依次往后成对比较,直到最后一对元素比较完成,这样一来就完成了一趟冒泡排序。(一趟冒泡排序,n个元素只需对n-1个元素比较)
  3、对总趟的所有元素,重复以上的步骤。需要注意,每趟排序会使得一个元素到其正确的位置。一趟结束后原先序列中首(尾) 元素改变,因此一趟循环仍旧从首元素/尾元素开始。而每次排序完成,都可去除一个元素。

  代码实现如下:

void bubble_sort(int arr[], int size)
{
	//总趟数
	for (int i = 0; i < size - 1; ++i)
	{
		int flag = 1;//用于判断数组本身是否已经有序

		//单趟数:每次j均从原始位置排序(j = 0),但每次排序的总数在减少(size - 1 - i)
		for (int j = 0; j < size - 1 - i; ++j)
		{
			
			if (arr[j] > arr[j + 1])//排升序
			{
				flag = 0;
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 1)//说明没有进入单趟交换
		{
			break;
		}
	}

}

int main()
{
	int arr[] = { 10,9,8,7,6,5,4,3,2,1 };

	//要求:写一个冒泡排序,将数组arr排为升序。
	int size = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, size);
	for (int i = 0; i < size; ++i)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
	return 0;
}

  
  
  冒泡排序的时间复杂度在最坏情况下是 O ( n 2 ) O(n^2) O(n2),其中 n 是待排序元素的数量。这是因为,在最坏情况下(即输入数组已经是逆序的),每次遍历都需要进行 n-1 次比较和可能的交换。由于有 n-1 次遍历(最后一次遍历不需要比较或交换),所以总的时间复杂度是 O ( n 2 ) O(n^2) O(n2)
  
  冒泡排序的空间复杂度是 O ( 1 ) O(1) O(1),因为它只需要常数个额外的空间来存储临时变量。
  
  
  
  
  
  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值