函数、数组

本文详细介绍了Java中的函数定义、重载及数组操作等内容,包括数组的声明与初始化、排序查找等实用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、函数

1. 函数就是在类中具有特定功能的一段程序,也叫方法。                                                        

2. 函数的基本语法格式:

       修饰符    返回值类型    函数名(参数类型  形式参数1,参数类型  形式参数2)

       {
              执行语句

             returnxxx;

        }

      其中,方法名,标识符的规则:首字母小写,后面单词首字母大写
                  参数列表:就是方法运行的时候,未知的参与运算的数据

注意:(1)当函数运算后,没有具体返回值时,用一个特殊的关键字标识,即void,当函数返回值类型为void时,函数中的return语句可以省略。

      (2)函数中只能调用函数,不可以定义函数;

      (3)定义函数时,函数的结果应该返回给调用着,交由调用者处理。

3.如何定义一个函数?

   (1). 首先明确函数的计算结果是什么;

   (2). 明确在定义功能的过程中是否需要未知的内容参与运算

4.函数的重载

    (1)概念

    在同一个类中(这是范围),允许存在一个以上的同名函数,只要他们的参数列表不一样即可(要么参数个数不一样,要么参数类型不一样)

    (2)重载的特点

    重载要求函数名相同但是参数列表不同,其余的返回值类型修饰符是否抛出异常与两个函数在一个类中是否构成重载没有关系

    (3)何时使用重载

    当定义函数的功能相同,但是参与运算的位置内容(也就是函数的参数)不同,这时候,可以根据函数具有相同的功能定义函数名称相同的函数,但是参数列表不同。函数名相同便于进行阅读。

二、数组

1.数组:同一种类型数据的集合,其实是一个容器。

2.数组的表达格式:

   (1)元素类型[] 数组名 = new   元素类型[元素个数或数组长度];

             示例:int[] arr = new int[5];

其中,int 数组中存储的数据的类型;

            []  表示数组;

    arr 数组名,数组的地址引用;

            new 创建实体;

    int 这个实体中存储的数据类型;

    []  表示数组;

    5  数组中可以存储5个数据。

   (2)元素类型[] 数组名 =new   元素类型[]{元素,元素,……};

               示例:int[] arr = new int[]{3,5,1,7};

3.数组的优势

   能够自动为数组中的元素自动从0开始进行编号,方便对元素的操作。

4.关键字new的作用

      (1)用来在内存中产生实体

      (2)实体:包括类的对象和数组(数组和类对象可以通称为new建立的实体)

5.java的内存结构

   java在启动时在内存中开辟了五块内存空间分别为方法区,本地方法区,寄存区, 堆和栈。

(1)内存的特点

       1)存放的内容:用于存储定义在方法中和局部代码块中局部变量

       2)栈内存的管理:所占用的空间直到相对应的代码块或者方法执行完就立即自动释放

(2)堆内存的特点

       1)存储的内容:通过new建立的实体全部存放到堆内存中

       2)每一个实体都有自己的内存地址值

       3)实体中的变量都有默认的初始化值

       4)当实体不再被使用的时候,会在不确定的时候,有垃圾回收器 (GC)回收(释放空间)

6. Java中的垃圾以及垃圾回收机制 (GC机制)

    (1)Java中的对象何时变成垃圾?

当一个堆内存中的对象在栈中没有引用指向它的时候,这个对象就被JVM视为垃圾

    (2)垃圾不会被立刻清理掉,而是在未知的时间点,JVM启动GC来回收这个对象所占用的空间。

    (3)Java中的垃圾回收机制(和C++相比)

Java中不用手动清除堆内存对象,只要将堆内存中的对象变成垃圾,这个垃圾对象就会被GC在某个不确定的时间自动清除掉。

7.数组的操作

(1)排序

    1)选择排序法:

    选择排序法,就是从第一个数开始和后面的每一个数进行比较,把小的换到前面,大的换到后边。

      

    2)冒泡排序法:把相邻的两个数进行比较,前边大后变小则换位。

   

例:对给定数组进行排序。{5,1,6,4,2,8,9} 

<span style="color:#333333;">import java.util.*;
class ArraySort 
{
	/*
	选择排序。
	内循环结束一次,最值出现头角标位置上。
	*/
	public static void selectSort(int[] arr)
	{
		for (int x=0; x<arr.length-1 ; x++)
		{
			for(int y=x+1; y<arr.length; y++)
			{
				if(arr[x]>arr[y])//没个数都会和后边所有的数进行比较。
				{
					swap(arr,x,y);//前边的值比后边的大,则交换位置
				}
			}
		}
	}
	/*
	冒泡排序
	*/
	public static void bubbleSort(int[] arr)
	{
		for(int x=0; x<arr.length-1; x++)
		{									
			for(int y=0; y<arr.length-x-1; y++)//-x:让每一次比较的元素减少;-1:避免角标越界。
			{
				if(arr[y]<arr[y+1])
				{
					swap(arr,y,y+1);
				}
			}
		}
	}

	/*
	发现无论什么排序。都需要对满足条件的元素进行位置置换。
	所以可以把这部分相同的代码提取出来,单独封装成一个函数。
	*/
	public static void swap(int[] arr,int a,int b)
	{
		int temp = arr[a];
		arr[a] = arr[b];
		arr[b] = temp;
	}
	public static void main(String[] args)
	{
		int[] arr = {5,1,6,4,2,8,9};		
		printArray(arr);<span style="font-family: SimSun; ">//打印排序前的数组排序前;</span>
		//排序
		selectSort(arr);//选择排序法
		//bubbleSort(arr);//冒泡排序法</span>
<span style="color:#333333;">		//Arrays.sort(arr);//java中已经定义好的一种排序方式。开发中,对数组排序通常使用该句代码。
		printArray(arr);<span style="font-family: SimSun; ">//打印排序后数组</span>		
	}</span>
<span style="color:#333333;"><span>	</span>//打印数组
	public static void printArray(int[] arr)
	{
		System.out.print("[");
		for(int x=0; x<arr.length; x++)
		{
			if(x!=arr.length-1)
				System.out.print(arr[x]+", ");
			else
				System.out.println(arr[x]+"]");

		}		
	}
}
</span>

(2)查找

    (1)排序查找:根据排序法找出大小,从而确定最大值和最小值,也可根据折半查找找出需要找到的数。

    (2)折半查找:同理于猜数游戏,能提高效率,但必须是在数组是有序的情况下才能实现。提高效率的原理是缩小比较范围,折半的两种方式,判断值方式和判断角标方式。将已知数字插入有规律的数组内还是用折半方法。

示例:将一个元素8插入一个有序的数组{3,4,6,7,9,12,45,68,79}里并打印出来,并且保证该数组还是有序的。关键是如何获取元素在数组中的位置。

<span style="color:#333333;">class  halfSearch{  
    public static void main(String[] args) {  
        int[] arr = {3,4,6,7,9,12,45,68,79};  
        int index1 = halfSearch1(arr,45);  
        System.out.println("index1="+index1);  
        int index2 = halfSearch2(arr,100);  
        System.out.println("index2="+index2);  
    }   
    //折半查找 1 :判断角标方式 
    public static int halfSearch1(int[] arr,int key){  
        int min = 0;                //最小下标  
        int max = arr.length-1;      //最大下标  
        int mid = (min + max)/2;     //中间下标  
        while (arr[mid]!=key){       //中间下标值和key不同  
            if (key>arr[mid])        //如果key大于最小下标值  
                min = mid+1;         //那么最小下标+1,往后移  
            else if (key<arr[mid])   //否则如果key小于最小下标值  
                max = mid-1;         //那么最大下标-1,往前移  
            if (min>max)             //如果最小下标大于最大下标,就是交错  
                return -1;           //那么返回-1 表示查询不到  
            mid = (min+max)/2;       //取中间下标  
        }  
        return mid;  
    }    
    //折半查找 2  :判断值方式
    public static int halfSearch2(int[] arr,int key){  
        int min = 0;  
        int max = arr.length-1;  
        int mid;  
        while(min<=max){  
           mid=(max+min)>>1;//右移位运算  
            if (key>arr[mid])  
                min = mid +1;  
            else if (key<arr[mid])  
                max = mid-1;  
            else  
                return mid;  
        }  
        return -1;  
    }  
}</span>

(3)查表法进制转换

    查表法:将所有的元素临时存储起来,建立对应关系。十六进制与十进制的对应关系如下: 

十六进制          0 1 2 3 4 5 6 7 8 9  A   B  C   D   E   F

十进制              0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

示例:十进制转换为二进制、八进制、十六进制

class ArrayTrans 
{
	public static void main(String[] args) 
	{
		toBin(-6);//调用转为二进制的方法
		toHex(-60);//调用转为十六进制的方法
		toBa(60);//调用转为八进制的方法

	}

	/*
	十进制-->二进制
	*/
	public static void toBin(int num)
	{
		trans(num,1,1);
	}

	/*
	十进制-->八进制
	*/
	public static void toBa(int num)
	{
		trans(num,7,3);
	}
	/*
	十进制-->十六进制
	*/
	public static void toHex(int num)
	{
		trans(num,15,4);
	}

	public static void trans(int num,int base,int offset)
	{

		if(num==0)
		{
			System.out.println(0);
			return ;
		}
		char[] chs = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
		char[] arr = new char[32];//定义一个临时容器。

		int pos = arr.length;

		while(num!=0)
		{
			int temp = num & base;
			arr[--pos] = chs[temp];
			num = num >>> offset;
		}
<span style="white-space:pre">		//存储数据的arr数组遍历。</span>
		for(int x=pos; x<arr.length; x++)
		{
			System.out.print(arr[x]);
		}

		return ;
	}
}

三、二维数组

二维数组的命名写法和特点:

    格式一:int[][] arr = new int[3][];

表示的意思是二维数组中有3个一维数组,并且每个一维数组都是默认初始化值null可以对这三个一维数组分别进行初始化

arr[0]= new int[3]; 

arr[1] = newint[1]; 

arr[2] = newint[2];

    格式二:int[][]arr = newint[3][2];

表示 定义了名称为arr的二维数组,二维数组中有3个一维数组,每一个一维数组中有2个元素,一维数组的名称分别为arr[0], arr[1], arr[2]。

给第一个一维数组1脚标位赋值为3写法是:arr[0][1] =3;

  

<think>嗯,用户问的是“函数数组指针”,这个术语有点容易混淆,我得先弄清楚他们具体指的是什么。首先,函数数组指针可能涉及三个概念:函数指针、数组指针,以及它们的组合。可能用户是想了解如何定义指向函数数组的指针,或者指向数组函数指针?不过更常见的情况可能是指向函数的指针数组,或者数组的指针,但需要结合函数的情况。 首先,我需要回顾一下C/C++中的相关概念。函数指针是指向函数的指针变量,例如int (*funcPtr)(int, int)可以指向一个接受两个int参数并返回int的函数数组指针则是指向数组的指针,比如int (*arrPtr)[10]指向一个包含10个int元素的数组。而函数数组指针可能是指一个数组,其元素是函数指针,或者是一个指针指向这样的数组。 用户可能是在学习这些复合类型时遇到了困惑。例如,定义一个包含多个函数指针的数组,或者一个指针指向这样的数组。这时候需要明确语法结构,因为C/C++的声明语法有时比较复杂。 比如,函数指针数组的正确声明应该是int (*funcArray[5])(int),这表示funcArray是一个有5个元素的数组,每个元素都是指向返回int且接受一个int参数函数的指针。而如果要定义一个指向这个数组的指针,应该怎么写?这时候可能需要使用typedef来简化。例如: typedef int (*FuncPtr)(int); FuncPtr (*arrPtr)[5] = &funcArray; 或者直接声明:int (*(*arrPtr)[5])(int) = &funcArray; 这样的声明看起来复杂,但分解起来可能更容易理解。用户可能需要具体的例子来理解如何声明和使用这样的指针。 另外,用户可能在实际编程中遇到需要传递函数指针数组的情况,或者需要动态分配这样的数组,这时候正确的指针操作就很重要了。例如,在回调机制或状态机设计中,函数指针数组很常见,而了解如何通过指针来操作这些数组是必要的。 还需要注意,函数指针和数组指针在语法上的区别。函数指针的声明需要参数列表,而数组指针则需要指定数组大小。当它们结合在一起时,声明的可读性可能会变差,因此使用typedef来分步定义可能是个好方法。 总结来说,用户需要了解如何正确声明和使用指向函数数组的指针,或者函数指针数组的指针。这时候,分步解析声明语法,提供示例代码,并解释每一步的作用,会很有帮助。同时,提醒用户注意语法中的括号位置,因为错误的放置会导致完全不同的类型解释。例如,int *funcArray[5]()表示一个返回int指针的函数数组,而int (*funcArray[5])()才是一个函数指针数组,返回int。 最后,可能还需要讨论应用场景,比如在实现策略模式、插件系统或者命令解析时,函数指针数组的指针如何被用来动态调用不同的函数,增强程序的灵活性和模块化。</think>好的,我来逐步解释“函数数组指针”的概念: 1. **基础概念分解** - **函数指针**:存储函数地址的变量,如 `int (*pFunc)(int)` - **数组指针**:指向数组的指针,如 `int (*pArr)[5]` - **函数数组指针**:指向“函数指针数组”的指针,属于复合类型 2. **语法结构解析** ```c // 定义函数指针类型 typedef int (*FuncPtr)(int); // 创建函数指针数组 FuncPtr funcArray[3] = {func1, func2, func3}; // 定义指向这个数组的指针 FuncPtr (*pFuncArray)[3] = &funcArray; ``` 等效的直接声明: ```c int (*(*pFuncArray)[3])(int) = &funcArray; ``` 3. **关键符号解析** ``` int (*(*ptr)[N])(params) │ │ │ └── 函数参数列表 │ │ └── 指向的数组长度 │ └── 指针声明符 └── 函数返回类型 ``` 4. **使用场景** - 需要传递整个函数指针数组时 - 需要修改函数指针数组的指向时 - 实现动态函数调度系统 5. **示例代码演示** ```c #include <stdio.h> int add(int a) { return a + 1; } int sub(int a) { return a - 1; } int main() { // 定义函数指针数组 int (*funcs[2])(int) = {add, sub}; // 定义指向数组的指针 int (*(*pFuncs)[2])(int) = &funcs; // 通过指针调用 for(int i = 0; i < 2; i++) { printf("Result: %d\n", (*pFuncs)[i](5)); } return 0; } ``` 6. **易错点注意** - 括号嵌套顺序错误会导致类型改变 - 数组长度必须与目标数组匹配 - 解引用时需要先取数组再访问元素 理解函数数组指针的关键是:它本质上是二级指针,指向一个包含函数指针的数组。通过分步类型定义和使用typedef可以显著提高代码可读性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值