数组2(笔记)

二维数组:
1.定义名为arr的二维数组
1) int[][] arr = new int[3][2];(动态初始化一)
二维数组中有3个一维数组每个一维数组中有2个元素。
2)int[][] arr =new int[3][];
arr[0] =new int[2];
arr[1] =new int[3];
arr[2] =new int[5];(动态初始化二)
二维数组中有3个一维数组,每个默认初始化null。不能写int[][] arr =new int[][5];
2.int [][] arr =new int[][]{{1,2,3},{4,5,6},{7,8,9}};(静态初始化)
定义一个名称为arr的二维数组,二维数组中有三个一维数组
每一个一维数组中具体元素也都已初始化
第一个一维数组 arr[0] = {1,2,3};
第二个一维数组 arr[1] = {4,5,6};
第三个一维数组 arr[2] = {7,8,9};
第三个一维数组的长度表示方式:arr[2].length;

public class TestArray2 {
    public static void main(String[] args) {

        int[] scores = new int[7];

        int[][] scores1;
        scores1 = new int[][] { { 1, 2, 3, 4 }, { 1, 2, 3 }, { 6, 7, 8 } };// 静态初始化

        String[][] names;
        names = new String[5][3];// 动态初始化1

        names = new String[3][];
        names[0] = new String[5];
        names[1] = new String[4];
        names[2] = new String[7];// 动态初始化2

        int[][] i = new int[3][2];
        i[1][0] = 78;
        i[2][1] = 99;

        System.out.println(i.length);
        System.out.println(i[1].length);
        System.out.println(names.length);
        System.out.println(names[0].length);

        System.out.println();

        for (int a = 0; a < scores1.length; a++) {

            for (int b = 0; b < scores1[a].length; b++) {
                System.out.print(scores1[a][b] + " ");
            }
            System.out.println();
        }

    }
}

3.数组排序
插入排序
直接插入排序、折半插入排序、Shell排序

交换排序
冒泡排序、快速排序(或分区交换排序)

选择排序
简单选择排序、堆排序

归并排序

基数排序

冒泡排序:相邻两元素进行比较,如有需要则进行交换,每完成一次循环就将最大元素排在最后(如从小到大排序),下一次循环是将其它的数进行类似操作。
手动:

    public void sort(int[] arr, String desc) {
        if (desc == "esc") {
            for (int i = 0; i < arr.length - 1; i++) {
                for (int j = 0; j < arr.length - 1 - i; j++) {
                    if (arr[j] > arr[j + 1]) {
                        // int temp = arr[j];
                        // arr[j] = arr[j + 1];
                        // arr[j + 1] = temp;
                        swap(arr, j, j + 1);
                    }
                }
            }
        } else if (desc == "desc") {
            for (int i = 0; i < arr.length - 1; i++) {
                for (int j = 0; j < arr.length - 1 - i; j++) {
                    if (arr[j] < arr[j + 1]) {
                        // int temp = arr[j];
                        // arr[j] = arr[j + 1];
                        // arr[j + 1] = temp;
                        swap(arr, j, j + 1);
                    }
                }
            }
        } else {
            System.out.println("Have wrong!");
        }

    }

    public void swap(int[] arr, int i, int j) {

        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

java.util.Arrays类中的sort()方法提供了数组元素排序功能

import java.util.*;
    public class Sort {
        public static void main(String[] args) {
            int [] number = {5,111,523,77,30,69,1260};
            Arrays.sort(number);
            for(int i = 0; i < number.length; i++)
                System.out.println(number[i]);
        }
    }

4.数组常见异常:
1)数组下标越界异常((ArrayIndexOutOfBoundsException)
2)空指针异常(NullPointerException)
arr引用没有指向实体,却在操作实体中的元素

<think>好的,我现在要帮用户查找关于树状数组的学习资料或教程。用户已经提供了三个引用内容,我需要先仔细阅读这些引用,理解它们的关键点,然后结合自己的知识来整理回答。 首先看引用[1],里面提到树状数组的特点是编程简洁,使用lowbit技术,代码效率高,比线段树更高效。这里可能需要解释一下lowbit是什么,以及为什么代码效率更高。引用[2]则更详细地介绍了树状数组的定义,用途是处理范围查询和单点更新,比线段树快。而引用[3]说明了当修改数组元素时,前缀和需要重新计算,树状数组解决了这个问题。 用户的问题是需要学习树状数组的教程或详解,所以我的回答需要结构清晰,分步骤讲解,可能包括概念、原理、核心操作、代码示例以及应用场景。同时,根据用户提供的系统级指令,数学公式要用$...$,独立公式用$$...$$,并且生成相关问题。 接下来要确保回答符合中文,正确使用LaTeX格式。比如lowbit的公式应该是$lowbit(x) = x \& (-x)$,需要用行内公式格式。此外,可能需要给出树状数组的结构示意图,但由于文本限制,可能需要用文字描述结构。 然后需要组织内容:先介绍树状数组的基本概念,然后讲解lowbit的原理,接着说明核心操作(更新和查询),给出代码示例,再讨论应用场景,最后根据引用内容添加参考资料。同时,在回答末尾生成相关问题,帮助用户深入理解。 要注意引用标记,在引用内容后自然添加[^1]、[^2]等。例如在讲解lowbit时引用[1],在解释应用场景时引用[2]和[3]。 需要检查是否有遗漏的重要点,比如树状数组的优缺点,与其他数据结构(如线段树)的比较,这些可能对用户有帮助。同时,代码示例需要正确,可能用Python或C++,但用户提供的引用中有C++,所以可能更倾向用C++示例,但用户之前的示例是Python,所以可能需要兼顾或说明。 最后,生成的相关问题要围绕树状数组的深入理解、应用、比较等方面,比如与线段树的区别,时间复杂度,如何扩展到多维等。 现在需要把这些思考整理成一个连贯的回答,确保每个部分自然衔接,引用正确,格式符合要求。</think>### 树状数组详解 树状数组(Binary Indexed Tree, BIT)是一种高效处理**单点更新**和**前缀和查询**的数据结构,尤其适合动态维护数组的场景。其核心思想是通过二进制索引的树状结构,将时间复杂度优化到$O(\log n)$。 #### 1. 基本原理与结构 树状数组利用二进制中$lowbit$技术划分区间。定义$lowbit(x) = x \& (-x)$,例如$lowbit(6)=2$(6的二进制为$110$,取最低位的1)[^1]。 树状数组中每个节点$c[i]$管理原数组$arr$的区间为$[i-lowbit(i)+1, i]$,例如: - $c[4]$管理$arr[1-4]$(因为$lowbit(4)=4$) - $c[6]$管理$arr[5-6]$(因为$lowbit(6)=2$) #### 2. 核心操作 **(a) 单点更新** 当修改$arr[k]$时,需更新所有覆盖$k$的节点。例如更新$arr[3]$时,依次更新$c[3], c[4], c[8], \dots$ **代码示例(C++)**: ```cpp void update(int k, int val) { while (k <= n) { c[k] += val; k += lowbit(k); } } ``` **(b) 前缀和查询** 求$arr[1..k]$的和时,从$c[k]$开始向祖先跳跃累加。例如查询$k=6$时,累加$c[6], c[4]$ **代码示例(C++)**: ```cpp int query(int k) { int res = 0; while (k > 0) { res += c[k]; k -= lowbit(k); } return res; } ``` #### 3. 应用场景 - **动态维护逆序对**:通过离散化+树状数组统计右侧小于当前元素的个数[^3] - **区间求和与单点修改**:例如实时统计股票价格波动 - **替代线段树**:在一维且无需复杂区间操作时,代码更简洁[^1] #### 4. 与线段树的对比 | 特性 | 树状数组 | 线段树 | |--------------|---------------|---------------| | 代码复杂度 | 极低(10行内)| 较高(递归或非递归) | | 功能范围 | 单点更新+前缀和 | 支持区间修改/查询 | | 时间复杂度 | $O(\log n)$ | $O(\log n)$ |
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值