JAVA學(xué)習(xí)第八天之?dāng)?shù)組

學(xué)習(xí)目的

  1. 掌握數(shù)組的概念
  2. 掌握一維數(shù)組和二維數(shù)組的定義、初始化、賦值及循環(huán)遍歷
  3. 掌握數(shù)組的常用方法(復(fù)制和擴容)
  4. 掌握基本算法的原理和使用(冒泡排序、選擇排序、二分查找)
  5. 了解Arrays工具類的使用和常用方法

一.數(shù)組

  1. 概念
    數(shù)組是一組數(shù)據(jù)的集合,是java提供的除了單個元素以外,可以存儲多個元素的集合。數(shù)組本身是一種引用數(shù)據(jù)類型,但數(shù)組中元素類型可以是基本類型,也可以是引用類型。但同一個數(shù)組只能存儲同一種類型,一個數(shù)組內(nèi)不能同時存儲基本數(shù)據(jù)類型和引用數(shù)據(jù)類型。
  2. 特點
  • 數(shù)組本身作為對象<存儲在堆內(nèi)存中>,而元素則作為數(shù)組對象的屬性;
  • 數(shù)組的長度在數(shù)組對象創(chuàng)建聲明后立即確定,過后無法再修改;
  • 數(shù)組中的元素根據(jù)下標(biāo)來標(biāo)識,第一個元素從 0 開始,類推到最后一個元素的下標(biāo)為 n-1,可通過下標(biāo)來訪問數(shù)組元素。
  1. 用途
  • 多元素的一個容器,一次可以存儲多個元素;
  • 作為方法的形式參數(shù),當(dāng)一個方法的形式參數(shù)是一個數(shù)組時,可以傳遞進(jìn)來一個數(shù)組對象。

1.1 一維數(shù)組

  1. 定義
    一維數(shù)組是指數(shù)組中存儲的是一個單一的元素,每個元素類型相同,且都只帶有一個下標(biāo)。其本質(zhì)上是一組相同類型數(shù)據(jù)的線性集合。
  2. 一維數(shù)組聲明
    <不建議立即聲明數(shù)組長度[int]>
  • 推薦:數(shù)組元素類型[] 變量名 = new 數(shù)組元素類型[數(shù)組元素個數(shù)];
  • 數(shù)組元素類型 變量名[] = new 數(shù)組元素類型[數(shù)組元素個數(shù)]。
       int[] i = {1,34,5,7,9,369};
//靜態(tài)初始化-第一種數(shù)組定義格式:推薦
       int[] j = new int[5];
        j[0] = 2;
        j[1] = 4;
        j[2] = 6;
        j[3] = 8;
        j[4] = 10;

//靜態(tài)初始化-第二種數(shù)組定義格式:不推薦
        int j[] = new int[5];
        j[0] = 2;
        j[1] = 4;
        j[2] = 6;
        j[3] = 8;
        j[4] = 10;
//一次定義多個數(shù)組
        int[] a, b, c;
  1. 數(shù)組賦值圖解


    一維數(shù)組賦值的內(nèi)存顯示.png

1.1.1 基本數(shù)據(jù)類型一維數(shù)組

  1. 概念
    基本類型數(shù)組的元素只能是統(tǒng)一的基本數(shù)據(jù)類型,int類型數(shù)組只能存int元素,double類型數(shù)組只能存double元素。
  2. 數(shù)組定義格式
    基本數(shù)據(jù)類型[] 變量名稱 = {基本元素 1,基本元素 2,...基本元素 n}
//靜態(tài)初始化-第一種數(shù)組定義格式:推薦
        int[] i = {1,2,3,4,5};
  1. 基本數(shù)據(jù)類型一維數(shù)組圖解


    基本數(shù)據(jù)類型的一維數(shù)組內(nèi)存模型.png

1.1.2 引用數(shù)據(jù)類型一維數(shù)組

引用類型數(shù)組的元素只能是統(tǒng)一的引用數(shù)據(jù)類型,String類型數(shù)組只能存String元素,Person類型數(shù)組只能存Person元素,Animal類型數(shù)組只能存Animal元素。

  1. 數(shù)組定義格式
    引用數(shù)據(jù)類型類型 變量名稱[] = {引用元素 1,引用元素 2,...引用元素 n}
        //靜態(tài)初始化引用類型數(shù)組,推薦該方式
        String[] s1 = {"張三","李四","王五","趙六","錢七"};
        //定義動態(tài)初始化數(shù)組,不推薦一開始就限定數(shù)組長度        
        String s3[] = new String[5];
        //動態(tài)初始化引用類型數(shù)組(同上)
        Person[] p = new Person[5];
        for (int m = 0;m<p.length;m++){
            Person ps = new Person();
            p[m] = ps;
            System.out.println(p[m].hashCode());
        }
  1. 引用數(shù)據(jù)類型一維數(shù)組圖解


    引用數(shù)據(jù)類型的一維數(shù)組內(nèi)存模型.png

1.1.3 數(shù)組初始化

  1. 定義
    在定義數(shù)組時,若不對數(shù)組中元素手動賦值初始化,系統(tǒng)為該類型的每個元素賦 對應(yīng)數(shù)據(jù)類型的默認(rèn)值。
  2. 靜態(tài)賦值
    在創(chuàng)建數(shù)組對象的時候直接賦值,<靜態(tài)初始化在編譯階段進(jìn)行,能減少運行時間>。
  3. 動態(tài)賦值
    先創(chuàng)建聲明一個數(shù)組,后續(xù)根據(jù)元素下標(biāo)再逐個賦值,<動態(tài)初始化在運行時進(jìn)行>。
  4. 引用數(shù)據(jù)類型賦值
    對于引用數(shù)據(jù)類型的數(shù)組,數(shù)組元素為對象內(nèi)存地址。因此賦予數(shù)組元素的值也是對象,不是賦予對象的屬性。
    若沒有對引用數(shù)據(jù)類型的數(shù)組手動賦值,系統(tǒng)默認(rèn)引用類型元素的初始值為null,訪問該數(shù)組元素時會引發(fā)空指針異常。
  5. 引用類型數(shù)組賦值圖解


    引用數(shù)據(jù)類型數(shù)組賦值.png

1.1.4 數(shù)組與多態(tài)

  1. 概念
    一個元素類型定義為父類型的數(shù)組,實際存入數(shù)組的元素可以為子類型。但若要使用到子類型的方法時,需要使用instanceof符號進(jìn)行類型轉(zhuǎn)換。
  2. 代碼示例
public static void main(String[] args) {
        // 創(chuàng)建一個Animal類型的數(shù)組
        Animal a1 = new Animal();
        Animal a2 = new Animal();
        Animal[] animals = {a1, a2};
        // 對Animal數(shù)組進(jìn)行遍歷
        for (int i = 0; i < animals.length; i++) {
            animals[i].move(); // 此處的move()方法是數(shù)組當(dāng)中Animal父類的move()方法
        }

        // 動態(tài)初始化一個長度為3的Animal類型數(shù)組
        Animal[] ans = new Animal[3];
        ans[0] = new Animal();// Animal數(shù)組中存放父類對象
        ans[1] = new Cat(); // Animal數(shù)組中存放子類Cat
       ans[2]= new Bird(); // Animal數(shù)組中存放子類Bird
        for (int i = 0; i < anis.length; i++){
            // 對取出來的對象進(jìn)行向下轉(zhuǎn)型,以調(diào)用子類重寫后的方法
            if(anis[i] instanceof Cat){
                Cat cat = (Cat)anis[i];
                cat.catchMouse();
            }else if(anis[i] instanceof Bird){
                Bird bird = (Bird)anis[i];
                bird.sing();
            }
        }
}

class Animal{
    public void move(){
        System.out.println("Animal move...");
    }
}
// Cat子類
class Cat extends Animal {
    public void move(){
        System.out.println("貓在走貓步!");
    }
    public void catchMouse(){
        System.out.println("貓抓老鼠!");
    }
}
// Bird子類
class Bird extends Animal {
    public void move(){
        System.out.println("Bird Fly!!!");
    }
    public void sing(){
        System.out.println("鳥兒在歌唱?。?!");
    }
}

1.1.5 數(shù)組擴容

  1. 概念
    數(shù)組從一開始定義時,就已經(jīng)限定了數(shù)組的長度,容量不再變。當(dāng)業(yè)務(wù)需求改變,需要存儲更多的數(shù)據(jù)元素時,舊數(shù)組已經(jīng)容納不下,因此要進(jìn)行數(shù)組擴容。
  2. 做法
  • 新建一個大容量的數(shù)組,
  • 將原數(shù)組中的數(shù)據(jù)一個一個拷貝到大數(shù)組當(dāng)中。
    從舊數(shù)組的指定下標(biāo)開始,拷貝指定長度的元素,到新數(shù)組指定的下標(biāo)開始,粘貼拷貝過來的元素。
  1. 關(guān)鍵
    調(diào)用System類中的arraycopy(Object src, int srcPos, Object dest, int destPos,int length)方法。
  • Object src:舊數(shù)組對象
  • int srcPos:舊數(shù)組下標(biāo)
  • Object dest:新數(shù)組對象
  • int destPos:新數(shù)組下標(biāo)
  • int length:拷貝長度
  1. 數(shù)組擴容內(nèi)存圖解


    數(shù)組擴容的內(nèi)存模型分析.png
  2. 代碼示例
public static void main(String[] args) {
        // java數(shù)組拷貝原理:arraycopy(舊數(shù)組,舊數(shù)組下標(biāo),新數(shù)組,新數(shù)組下標(biāo),拷貝長度)
        //System.arraycopy(Object src,  int srcPos, Object dest, int destPos,int length);

        // 拷貝源(舊數(shù)組)
        int[] src = {1, 11, 22, 3, 4};
        // 拷貝目標(biāo)(新數(shù)組)
        int[] dest = new int[20]; 
        System.arraycopy(src, 1, dest, 3, 2);//從舊的下標(biāo)1開始,拷貝到新的下標(biāo)3下,長度為2
        System.arraycopy(src, 0, dest, 0, src.length); //拷貝全部元素
        for (int i = 0; i < dest.length; i++) {
            System.out.println(dest[i]);
        }
        // 引用數(shù)據(jù)類型數(shù)組的拷貝
        String[] strs = {"hello", "world!", "java", "oracle", "mysql", "jdbc"};
        String[] newStrs = new String[20];
        System.arraycopy(strs, 0, newStrs, 0, strs.length);
        for (int i = 0; i < newStrs.length; i++) {
            System.out.println(newStrs[i]);
        }
        //拷貝對象類型數(shù)組:存儲的對象內(nèi)存地址,拷貝的也是對象內(nèi)存地址        
        Object[] objs = {new Object(), new Object(), new Object()};
        Object[] newObjs = new Object[5];
        System.arraycopy(objs, 0, newObjs, 0, objs.length);
        for (int i = 0; i < newObjs.length; i++) {
            System.out.println(newObjs[i]);
        }
    }
  1. 注意點
  • 數(shù)組擴容效率較低:數(shù)組擴容涉及到拷貝問題,在以后的開發(fā)中應(yīng)盡可能少的進(jìn)行數(shù)組拷貝;
  • 在創(chuàng)建數(shù)組對象時預(yù)估長度:預(yù)估準(zhǔn)確數(shù)組定義的長度,可以減少數(shù)組的擴容次數(shù),提高開發(fā)效率。

1.2 string[] args數(shù)組

  1. 概念
    在最常使用main方法中,main方法的參數(shù)列表也是一個數(shù)組,且是String類型數(shù)組。main方法雖然是由開發(fā)者編寫,由jvm自動執(zhí)行的一個方法,但main方法的參數(shù)數(shù)組args是由開發(fā)者編寫的調(diào)用程序傳入的。
  2. 位置
    程序的主方法入口,main()方法的形式參數(shù)列表。
  3. 經(jīng)典代碼示例
//模擬系統(tǒng)登錄:使用main方法參數(shù)列表接收控制臺輸入的用戶名和密碼,并完成判斷
public class ArrayTest06 {
    public static void main(String[] args) {
        // 輸入?yún)?shù)必須為 2個,用戶名和密碼
        if(args.length != 2){
            System.out.println("請輸入用戶信息參數(shù),參數(shù)包括用戶名和密碼");
            return;
        }
        // 獲取參數(shù)列表中的用戶名和密碼,判斷是否正確
        String username = args[0]; // 取出用戶名
        String password = args[1]; // 取出密碼
        // 假設(shè)用戶名是admin,密碼是123表示登錄成功
        //if(username.equals("admin") && password.equals("123")){ // 易出現(xiàn)空指針異常。
        // 采用以下編碼風(fēng)格避免出現(xiàn)空指針異常(老程序員的一條編程經(jīng)驗)
        if("admin".equals(username) && "123".equals(password)){
            System.out.println("登錄成功,歡迎[" + username + "]回來");
            System.out.println("歡迎您使用該系統(tǒng)....");
        }else{
            System.out.println("驗證失敗,用戶名不存在或者密碼錯誤!");
        }
    }
}

1.3 二維數(shù)組

  1. 定義
    二維數(shù)組是指數(shù)組中的每個元素都是一個一維數(shù)組,本質(zhì)是以 數(shù)組 作為元素的數(shù)組。二維數(shù)組的使用類似于直角坐標(biāo)系,通過坐標(biāo)可以獲得指定元素。
  2. 二維數(shù)組聲明
  • 數(shù)組元素數(shù)據(jù)類型[][] 變量名 = new 數(shù)組元素數(shù)據(jù)類型[][];
  • 數(shù)組元素數(shù)據(jù)類型 變量名[][] = = new 數(shù)組元素數(shù)據(jù)類型[][];
//定義二維數(shù)組,推薦該方式
int[][] data = new int[][];

//c++定義二維數(shù)組,不推薦
int   data[][]  =  new  int[2][3];//定義一個2行,3列的二維數(shù)組
  1. 二維數(shù)組初始化
    靜態(tài)初始化:int[][] data = {{元素1,元素2},{元素1,元素2,元素3,元素4}};
//初始化一維數(shù)組
        int[] a = {1,2,4,45,6,68,3};
        int[] b = {9,2,44,56,68,3,23};
        int[] c = {8,2,4,7,2,435,7,68};

        //靜態(tài)初始化二維數(shù)組
        int[][] data = {{1,2,3,},{11,22,33},{1,2,4,8},{3,6,9,0}};
        //二維數(shù)組的元素可以直接賦值"一維數(shù)組對象"
        int[][] nm = {a,b,c};
  1. 二維數(shù)組的遍歷(分兩步)
  • 先獲取"行":即先獲取二位數(shù)組的元素--一維數(shù)組,每一個一維數(shù)組本身作為一行;
  • 獲取"列":獲取得到每一個一維數(shù)組后,開始遍歷一維數(shù)組的元素,每一個一維數(shù)組元素就是一列;
        //定義一個具有三個元素的二維數(shù)組
        int[][] nm = {{1,3,5},{2,4,6},{7,8,9}};
        for (int i = 0;i<nm.length;i++){    //外層獲得元素是每一個一維數(shù)組
            for (int j=0;j<nm[i].length;j++){   //內(nèi)層從每一個一維數(shù)組中獲取元素
                System.out.println(nm[i][j]);//i=第幾個一維數(shù)組,j=第i個一維數(shù)組中的第j個元素
            }
        }

1.3 多維數(shù)組

  1. 定義
    多維數(shù)組指的是數(shù)組中的每一個元素都是二維數(shù)組。
  2. 分類
  • 一維數(shù)組:數(shù)組元素為普通數(shù)據(jù)類型
  • 二維數(shù)組:數(shù)組元素為一維數(shù)組
  • 三維數(shù)組:數(shù)組元素為二維數(shù)組

二. 數(shù)組和算法

  1. 算法概念
    如何將文字描述轉(zhuǎn)換為有效率、高效率的代碼輸出。

2.1 冒泡排序(重點)

  1. 算法要求
    對于一個無序的數(shù)組,要求按從小到大排序輸出。
  2. 實質(zhì)
    利用水中相鄰泡泡比較的原理,最大氣泡最先升出水面。冒泡算法從數(shù)組最小下標(biāo)開始,每次比較下標(biāo) n 和 n+1兩個元素,若大小不相等則交換位置,繼續(xù)比較n+1和n+2下標(biāo)的元素。每一輪升出一個最大元素排最后,每下一輪減少一個元素進(jìn)行比較。
  3. 特點
  • 一個數(shù)組有幾個元素a.length,就比較 a.length-1輪;
  • 每一輪比較幾次,就交換幾次位置;
  • 保證每一輪比較都有一個數(shù)移到最右邊(最后面),每下一輪可以減少一個元素的比較。
  1. 實現(xiàn)原理
  • 先根據(jù)數(shù)組的長度,獲取總的排序輪數(shù) = 數(shù)組.length - 1;
  • 根據(jù)每一輪的最大下標(biāo),確定每一輪比較的次數(shù),比較次數(shù) = 最大的下標(biāo)數(shù) - 1;
  • 開始每一輪比較,從數(shù)組的最左邊開始<下標(biāo)為0開始>,逐個往右比較
    取出第 0 號下標(biāo)的元素 和 第 1號下標(biāo)的元素比較
    如果0 號數(shù)據(jù)大于1號數(shù)據(jù)則進(jìn)行交換,否則不進(jìn)行交換
    在第一次比較交換了數(shù)據(jù)后的基礎(chǔ)上
    取出1號下標(biāo)元素 和 2號下標(biāo)元素,重復(fù);
    取出2號下標(biāo)元素 和 3號下標(biāo)元素,重復(fù);
    取出3號下標(biāo)元素 和 4號下標(biāo)元素,重復(fù);
    取出n-1號下標(biāo)元素 和 n號下標(biāo)元素,重復(fù);
  • 每完成一輪比較,可以確定一個最大的數(shù)排到最右邊,下一輪的比較則較少一個數(shù);
  • 開始下一輪,最大下標(biāo) -1,比較次數(shù)-1;
  • 重復(fù)以上步驟。
  1. 圖解


    冒泡排序.png
  2. 代碼實現(xiàn)
int[] data = {3,1,6,2,5};
        //先根據(jù)數(shù)組長度,確定總的比較輪數(shù)
        for (int i=data.length-1; i>0; i--) {
            //開始每一輪的比較,第一輪有data.length-1個數(shù),每一輪減少一個
            for (int j=0; j<i; j++) {
            //開始比較,每一次都從下標(biāo)0開始和相鄰下標(biāo)比較,直到每次的最大下標(biāo)
            //第一輪最大下標(biāo)為4,則依次比較下標(biāo)01,12,23,34
            //第二輪最大下標(biāo)為3,則依次比較下標(biāo)0和1,1和2,2和3
            //第三輪最大下標(biāo)為2,則依次比較下標(biāo)0和1,1和2
            //第四輪最大下標(biāo)為1,則依次比較下標(biāo)0和1
                //若前一個數(shù)大于后一個數(shù),兩數(shù)進(jìn)行交換
                if (data[j] > data[j+1]) {
                    int temp = data[j];//前面較大值 暫存 到中間變量
                    data[j] = data[j+1];//將后面較小的值賦給前面一個下標(biāo)
                    data[j+1] = temp;//將暫存的最大值賦給后面一個下標(biāo)
                }
            }
        }
        //對排序完的數(shù)組進(jìn)行遍歷輸出
        for (int i=0; i<data.length; i++) {
           System.out.println(data[i]);
        }

2.2 選擇排序(重點)

  1. 算法要求
    對于一個無序的數(shù)組,要求按從小到大排序輸出。
  2. 實質(zhì)
    利用相對固定的第一個位置的元素跟其他位置的所有元素比較,得出最小元素再和第一個位置的元素交換位置。
  3. 保證
    默認(rèn)每一輪的比較都從左邊"第一個下標(biāo)"開始,保證了每一輪都有一個最小元素移到最左邊,下一輪減少一個元素的比較。
  4. 特點
    對冒泡排序進(jìn)行改進(jìn),使交換次數(shù)減少,但比較次數(shù)沒有減少<每一輪比較只交換一次位置>。
  5. 選擇排序原理
  • 先根據(jù)數(shù)組長度確定總的比較輪數(shù),總輪數(shù) = 數(shù)組.length - 1;
  • 每一輪都從左邊的下標(biāo)開始,第一輪下標(biāo)0開始,第二輪下標(biāo)1開始,最后一輪數(shù)組.length - 1開始比較最后兩個數(shù);
  • 定義初始下標(biāo):存儲每一輪從相對最左端開始的下標(biāo)
    將下標(biāo)為 0 的元素 和 下標(biāo)為1,2,3,4的元素依次比較
    如果找到比 初始下標(biāo)小 的元素,將該元素下標(biāo) 賦給 初始下標(biāo)
    然后按當(dāng)前最小元素的下標(biāo),繼續(xù)往后依次比較
    直到比較完每一輪中所有的元素
  • 若初始下標(biāo)的元素就是最小值,不需要換位置;若不是,把最小的元素和初始下標(biāo)元素位置互換;
  • 完成一輪后,初始下標(biāo)開始+1,初始下標(biāo)從0到1,1到2,2到3,n-2到n-1,重復(fù)以上步驟的比較。
  1. 圖解


    選擇排序.png
  2. 代碼實現(xiàn)
        int[] data = {3,1,6,2,5,4,7};
        //根據(jù)數(shù)組的長度確定,總的輪數(shù)<交換的次數(shù)>
        for (int i=0; i<data.length; i++) {
            int min = i;//每一輪比較的初始元素下標(biāo),從左邊開始
            //每一輪從初始下標(biāo)與初始下標(biāo)的下一個元素開始進(jìn)行比較
            for (int j=i+1; j<data.length; j++) {
             //第一輪,初始元素下標(biāo)為0,則從下標(biāo)1元素開始比較;
             //第二輪,初始元素下標(biāo)為1,則從下標(biāo)2元素開始比較;
             //第三輪,初始元素下標(biāo)為2,則從下標(biāo)3元素開始比較;
             //第n-1輪,初始元素下標(biāo)為n-2,則從下標(biāo)n-1元素開始比較
                //若初始下標(biāo)元素大于比較的元素,則互換下標(biāo),繼續(xù)往下比較
                if (data[j] < data[min]) {
                    min = j;//互換較小元素的 下標(biāo),繼而往下比較
                }
            }
            //每完成一輪比較,進(jìn)行最小元素位置的交換
            //若初始下標(biāo)就是最小下標(biāo),則不用交換
            if (min != i) {
                int temp = data[i];//將每一輪最小元素 賦給 中間量暫存
                data[i] = data[min];//將初始位置的元素 互換到本輪最小元素位置
                data[min] = temp;//將暫存的最小元素 換到 初始位置中
            }
        }
        //遍歷最終排序的數(shù)組
        for (int i=0; i<data.length; i++) {
            System.out.println(data[i]);
        }

2.3 二分查找(折半查找)

  1. 要求
    給定一個已經(jīng)排序好的數(shù)組,查找出符合條件的一個元素。
  2. 查找方式
    遍歷數(shù)組中的所有元素,逐個查找。
  3. 實質(zhì)
    在一個排序好的數(shù)組中,找到期望值的元素下標(biāo),并輸出。
  4. 實現(xiàn)原理
  • 對于一個已經(jīng)排好序的數(shù)組,從數(shù)組中查找一個期望值;
  • 先初始化兩個變量,數(shù)組起始元素的下標(biāo)為0,數(shù)組末位元素的下標(biāo)為 數(shù)組.length - 1;
  • 在已排序的數(shù)組里循環(huán)的二分 進(jìn)行查找;
  • 循環(huán)條件:起始下標(biāo)元素 < 末位下標(biāo)元素;
  • 執(zhí)行循環(huán)體:定義二分的中間下標(biāo) = ( 起始下標(biāo) + 末位下標(biāo) )/ 2
    若中間下標(biāo)的元素和期望值相等,直接返回中間下標(biāo);
    若中間下標(biāo)的元素 小于期望值,則從后半段數(shù)組中重新查找,且起始下標(biāo)更新為 當(dāng)前中間下標(biāo) + 1,末位下標(biāo)不變;
    若中間下標(biāo)的元素 大于期望值,則從前半段數(shù)組中重新查找,且起始下標(biāo)不變,末位下標(biāo)更新為 當(dāng)前中間下標(biāo) - 1;
    若數(shù)組中沒有這個期望值元素,直接返回 -1。
  1. 圖解

  2. 代碼解釋

public static void main(String[] args) {
        //定義一個數(shù)組,必須有序,才能進(jìn)行二分查找
        int[] data = {1,3,6,9,11,21,23,24,32,33,34,41};
        //在數(shù)組中查找指定元素,返回該元素下標(biāo)
        int index = binarySearch(data, 18);
        System.out.println(index);//找不到目標(biāo)值18,返回-1

        int index2 = binarySearch(data,11);
        System.out.println(index2);//輸出目標(biāo)值下標(biāo)為:4

        int index3 = binarySearch(data,33);
        System.out.println(index3);//輸出目標(biāo)值下標(biāo)為:9
    }

    private static int binarySearch(int[] data, int i) {
        //定義每一次二分的初始下標(biāo),下標(biāo)從0開始
        int begin = 0;
        //定義每一次二分的末位下標(biāo),最開始是數(shù)組的長度-1
        int end = data.length - 1;

        //判斷數(shù)組是否有序:起始下標(biāo)和末位下標(biāo)的元素大小
        //不能用if控制語句,二分查找是循環(huán)、不斷取2的過程,要用while
        while(data[begin] <= data[end]){
            //定義中間元素的下標(biāo):中間 =(起始+末位)/2         
            int mid = (begin + end)/2;
            //根據(jù)中間下標(biāo)的元素值 和 目標(biāo)值匹配
            if (data[mid] == i){
                return mid;
            }else if (data[mid] >= i){
                //中間元素值 大于 目標(biāo)值,下一次二分從前半段中查找
                //前半段初始下標(biāo)不變,結(jié)束下標(biāo)為中間下標(biāo)-1
                end = mid - 1;
            }else if (data[mid] <= i){
                //中間元素值 小于 目標(biāo)值,下一次二分從后半段中查找
                //前半段的末位下標(biāo)不變,初始下標(biāo)為中間下標(biāo)+1
                begin = mid + 1;
            }
        }
        //執(zhí)行到這里,說明以上找不到目標(biāo)值,返回-1 表示查找失敗
        return -1;
    }

2.4 快速排序

  1. 原理

  2. 圖解

  3. 代碼解釋

2.5 Arrays工具類

  1. 概念
    Arrays類是java提供的用來操作數(shù)組的各種方法的工具類。在該類中提供了 排序和搜索 數(shù)組的方法,在這些方法的底層已經(jīng)封裝好了算法實現(xiàn)。不需要開發(fā)者自己編寫。Arrays類還包含一個允許將數(shù)組作為列表 來查看的靜態(tài)工廠。
  2. 常用方法
  • void sort(數(shù)組名):Arrays工具類封裝好的排序方法,調(diào)用該方法時,直接傳遞進(jìn)入一個數(shù)組即可對該無序數(shù)組進(jìn)行排序;
  • int binarySearch(數(shù)組名, 期望值):Arrays工具類封裝好的二分查找方法,調(diào)用該方法時,直接傳遞進(jìn)入一個數(shù)組和期望值即可,返回期望值的下標(biāo)。

常見面試題

  1. 描述一下equals() 方法和 hashcode() 方法的關(guān)系?
    答:
  • 兩個對象hashCode()相等,對象不一定相等;
  • 兩個對象 equals 相等,那么它們的 hashcode 一定相等。
  • 兩個對象 equals 不相等,那么它們的 hashcode 并不要求不相等<一般建議不相等>;
  • 對象在堆內(nèi)存中是存儲在HashSet或HashMap中的,HashSet底層采用的是 數(shù)組 + 單向鏈表組合存儲,數(shù)組中的每一個元素都是單向鏈表。每一個對象都是存儲在數(shù)組中,而對象調(diào)用hashCode()方法得到的哈希地址--經(jīng)過哈希算法的運算,最終得到對象在數(shù)組中的下標(biāo)。
  • 但是由于每一個數(shù)組下標(biāo)上的元素都是單向鏈表,因此該位置上存在多個元素,該位置鏈表上的元素hashCode()都相同,但對象不一定相同。還需要比較對象的每一個屬性值,也就是需要使用 equals()方法。
  • 當(dāng)兩個對象hashCode()不相同時,認(rèn)為兩個對象在數(shù)組中的下標(biāo)不一樣,因此兩個對象也不同。
  1. 使用數(shù)組模擬棧數(shù)據(jù)結(jié)構(gòu)?
/*使用一維數(shù)組,模擬棧數(shù)據(jù)結(jié)構(gòu):
        1、這個棧可以存儲java中的任何引用類型的數(shù)據(jù)。
        2、棧中提供push方法模擬壓棧(棧滿要有提示信息)
        3、棧中提供pop方法模擬彈棧(??找灿刑崾拘畔ⅲ?        4、編寫測試程序,new棧對象,調(diào)用push pop方法來模擬壓棧彈棧的動作。
        5、假設(shè)棧的默認(rèn)初始化容量是100
    思路:
        1、定義一個一維數(shù)組,有一個棧頂元素永遠(yuǎn)指向數(shù)組第一個下標(biāo)(數(shù)組未有數(shù)據(jù)時,初始化下標(biāo)是-1,棧頂元素也為-1)
        2、push壓棧就是給一維數(shù)組添加一個元素(傳入?yún)?shù)),下標(biāo)往上加一,棧頂元素指向增加后的下標(biāo)
        3、pop彈棧相當(dāng)于給一維數(shù)組刪除一個元素,實際只是棧頂元素往下移動,下標(biāo)往下減一
        4、無論壓棧、彈棧都要先判斷該數(shù)組空間是否能已滿,或者是否還有元素可以彈出
 */
public class Stack{
    //Object[] ojbs = new Object[100];
    //定義一個可以存儲任何數(shù)據(jù)類型的一維數(shù)組    
    Object[] ojbs;
    //棧幀:永遠(yuǎn)指向棧頂部元素,最初棧為空
    //private int index = 0; // index==0,表示棧幀指向頂部元素上方
    //private int index = -1; // index==-1,表示棧幀指向頂部元素
    int index;//棧頂元素

    public Stack() {
        this.ojbs= new Object[10];//初始化數(shù)組的容量
        index = -1;//初始化棧幀,并讓棧幀指向棧頂元素(-1表示棧一開始為空)
    }
    public Stack(Object[] ojbs){
        this.ojbs = ojbs;
    }

    public Object[] getOjbs() {
        return ojbs;
    }
    public void setOjbs(Object[] ojbs) {
        this.ojbs = ojbs;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }

    //壓棧--往數(shù)組中添加元素
    public void push(Object obj){
        if(index >= ojbs.length-1){  //下標(biāo)永遠(yuǎn)小于等于數(shù)組長度-1
            System.out.println("棧已滿,不能再添加啦!");
            return;
        }
        //棧未滿,可以壓棧。index初始=-1指向棧頂元素,壓入數(shù)據(jù)時,index自增+1;
        index++;//index由-1變成0,元素可以壓入
        ojbs[index] = obj;//將壓入元素賦給棧頂下標(biāo)
        System.out.println(obj +"壓棧元素成功,棧幀指向:" + index);
    }

    //出棧不是刪除元素,只是棧頂元素(下標(biāo))往下移動,下標(biāo)改變代表刪除
    public void pop(){
        //if (ojbs.length<0){ //ojbs.length表示數(shù)組的長度,出棧不是刪除數(shù)組,因此長度不會小于0
        if (index < 0){
            System.out.println("棧已空,無法繼續(xù)刪除啦!");
            return;
        }
        //棧未空,有元素可以繼續(xù)刪除
        System.out.print(ojbs[index] + "出棧成功啦!");//先出棧
        index--;//棧頂元素自減1
        System.out.println("棧幀指向:" + index);
    }
}

//測試
public static void main(String[] args) {
        //創(chuàng)造一個棧對象,初始化數(shù)組容量為100,棧頂元素為-1
        Stack st = new Stack();
        //調(diào)用push(),測試壓棧
        st.push(new Object());//java.lang.Object@4554617c壓棧元素成功,棧幀指向:0
        ...//此處重復(fù)壓棧8次
        st.push(new Object());//java.lang.Object@330bedb4壓棧元素成功,棧幀指向:9
        //數(shù)組初始容量只有10,超過10不能再壓棧
        st.push(new Object());//棧已滿,不能再添加啦!

        //調(diào)用pop(),測試出棧
        st.pop();//java.lang.Object@330bedb4出棧成功啦!棧幀指向:8
        ...//此處重復(fù)出棧8次
        st.pop();//棧已空,無法繼續(xù)刪除啦!
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容