01、數據結構與算法--順序表

正式進入數據結構的學習,先從預備知識學起,戒焦戒躁戒焦戒躁...


一、泛型的引入

1、為什么需要泛型?

先來看一個題目:

實現一個類,類中包含一個數組成員,使得數組中可以存放任何類型的數據,也可以根據成員方法返回數組中某個下標的值

在沒有泛型理念的思路可能是這樣:

public class java0810 {public Object[] array = new Object[5];//成員變量public void set(int a,Object b){this.array[a] = b;}public Object get(int c){return array[c];}public static void main(String[] args) {java0810 x = new java0810();x.set(0,"哈哈");x.set(1, 2);String y1 = (String) x.get(0);int y2 = (int) x.get(1);  //需要強轉,因為是object類型System.out.println(y1);System.out.println(y2);}
}

我們通過Object類做到了讓一個數組中放入不同類型的數據,但在接收數據的時候需要對其進行強轉,很麻煩


于是我們想到使用泛型來解決這個問題:

public class java0810<T> {  //變動1public Object[] array = new Object[5];public void set(int a,T b){this.array[a] = b;}public T get(int c){return (T)array[c]; //變動2}public static void main(String[] args) {    //變動3java0810<Integer> x1 = new java0810<>();//規定了存放數據的類型x1.set(0,1);x1.set(1,2);int y1 = x1.get(0);int y2 = x1.get(1);System.out.println(y1);System.out.println(y2);java0810<String> x2 = new java0810<>();x2.set(0,"巨浪");x2.set(1,"M14大人");String y3 = x2.get(0);String y4 = x2.get(1);System.out.println(y3);System.out.println(y4);}

所有的變動之處需要理解,這樣做的好處就是:

“在新建一個對象時就規定了存放數據的類型,可以讓系統幫忙檢查同時不用強轉了”

想要深入理解背后的邏輯可以搜索擦除機制橋接方法


2、泛型類的上界

我們常常用 <? extends T> 的方式來指定約束泛型類型的上限,從而約束了‘ ?’只能是T或者其子類

來看一個題目:

寫一個泛型類,求數組中的最大值,數組的類型需要通過泛型類型來指定

                            //這是一個泛型類public class java0811<T extends Comparable<T>>  {//泛型類的上界public T find(T[] array){int i = 0;T max = array[0];for(i = 1;i < array.length;i++){if(array[i].compareTo(max) > 0){max = array[i];}}return max;}public static void main(String[] args) {java0811<Integer> y1 = new java0811<>(); //指定數組存放的類型java0811<String> y2 = new java0811<>();Integer []array1 = { 4, 3, 2, 91, 500 };String  []array2 = {"巨浪", "M14大人","騰龍"};int z = y1.find(array1);     //Integer或者int都可以String w = y2.find(array2);System.out.println(z);System.out.println(w);}}

這里通過實現了Comparable接口,指定了上界,從而可以使用comparaTo方法進行數字或者字符串的無差別比較

當然了,你也可以寫成是一個泛型方法:

 public class java0811 {//這就是泛型方法public <T extends Comparable<T>> T find(T[] array){int i = 0;T max = array[0];for(i = 1;i < array.length;i++){if(array[i].compareTo(max) > 0){max = array[i];}}return max;}public static void main(String[] args) {java0811 x = new java0811();  //沒有指定類型,因為它不是泛型類了Integer []array1 = { 4, 3, 2, 91, 500 };int y = x.find(array1);System.out.println(y);}
}

可以觀察一下里面的變動


二、通配符

1、概念:

通配符通過上下界(extends/super)實現了比泛型類型參數更靈活的類型關系控制,并遵循PECS原則(在值設置和取出時有特定約束)。

我們先來看看通過泛型的方式存放和取出數據:

class Food{                 
}
class Fruit extends Food{     //先明確了繼承關系
}
class apple extends Fruit{
}
class banana extends Fruit{
}public class Plate<T>{        //設置了一個泛型類public T array;public void set(T array){this.array = array;
}public T get(){return array;
}public static void main(String[] args) {Plate<apple> x1= new Plate<>();    //表示只能放入apple對象x1.set(new apple());Plate<banana> x2 = new Plate<>();  //同理x2.set(new banana());//     Plate<Food> x3 = new Plate<>();
//      fun1(x3);                      //會失敗,因為通配符所以只能傳入Fruit的子類fun1(x1);fun1(x2);}//通配符的上界
public static void fun1(Plate<? extends Fruit> z){//指定一個容器,存放的類型是Fruit或子類System.out.println(z.get());
}

這里通過fun來打印數據,接收的類型需要是Fruit或者其子類

2、通配符的上界:

采用<? extends T>的方式,在該方法中不能寫入子類,但可以接收T的子類

public static void fun1(Plate<? extends Fruit> z){//指定一個容器,存放的類型是Fruit或子類System.out.println(z.get());//    z.set(new apple());
//    z.set(new banana());     設置失敗,不能知道傳入的是哪個子類Fruit fruit = z.get();      //得到的一定是Fruit的子類System.out.println(fruit);  //成功了,同時打印了apple跟banana}

3、通配符的下界:

采用<? super?T>的方式,在該方法中主要用于寫入,接收時要用Object類保證安全

public static void main(String[] args) {Plate<Food> x3 = new Plate<>();x3.set(new Food());fun2(x3);}
public static void fun2(Plate<? super Fruit> t){t.set(new Fruit());     //可以放自己以及子類t.set(new apple());t.set(new banana());    //會打印最后一個傳入的值//   Food food = new Fruit();
//   Fruit fruit2 = (Fruit) food;     //這樣做就安全//    Fruit fruit2=(Fruit) new Food();//但是這樣直接指向不安全,打印不出來結果//    Fruit fruit3 = (Fruit) t.get(); //覺得這個寫法突兀的就向上看,也不安全Object o = t.get();               //Object來接收就安全了System.out.println(o);
}

小總結:通配符上界不能寫入子類但能接收子類

? ? ? ? ? ? ? ?通配符下界只能寫入自己以及子類,只能接收自己以及父類?


三、順序表

順序表(Sequential List)?是一種線性表,它用一段地址連續的存儲單元依次存儲線性表的數據元素

核心比喻:電影院座位

你可以把順序表想象成電影院里一排連續的座位

  1. 連續存儲:這些座位是緊挨著的,一個接一個,擁有固定的座位號(如1排1座、1排2座...)。這就是“順序”的含義——數據在物理內存中是連續存儲的。

  2. 快速“按號找座”:如果你想找第5個座位上坐的是誰,你可以立刻計算出來并直接走過去。

  3. “插隊”與“離場”麻煩

    • 插入:如果這排座位已經坐滿了,你想在中間加一個人,那么從這個位置開始以后的所有人都需要向后移動一個位置,才能空出一個新的座位。

    • 刪除:同理,如果中間有一個人離開了,那么他后面的所有人都需要向前移動一個位置來填補空位,以保持座位的連續性。

這是一個自己實現的順序表:

public interface IList {void add(int data); // 新增元素,默認在數組最后新增void add(int pos, int data); // 在 pos 位置新增元素boolean contains(int toFind); // 判定是否包含某個元素int indexOf(int toFind); // 查找某個元素對應的位置int get(int pos); // 獲取 pos 位置的元素void set(int pos, int value); // 給 pos 位置的元素設為 valuevoid remove(int toRemove); //刪除第一次出現的關鍵字keyint size(); // 獲取順序表長度void clear(); // 清空順序表void display(); // 打印順序表,注意:該方法并不是順序表中的方法,為了方便看測試結果給出的boolean isFull();boolean isEmpty();}
import java.util.Arrays;public class MyarrayList implements IList{public int[]array;public int useside;public static final int l = 5;public  MyarrayList(){array = new int[l];}//檢查是否放滿了@Overridepublic boolean isFull() {if(useside == array.length){return true;}return false;}@Overridepublic boolean isEmpty() {if(useside == 0){return true;}return false;}//自己設置的2倍擴容public void grow(){array = Arrays.copyOf(array,2 * array.length);}//在順序表中,默認在最后位置添加元素,這個沒有@Overridepublic void add(int data) {array[useside++] = data;}public void checkpos(int pos){if(pos < 0 || pos > useside){//這里在數組末尾插入是合法的throw new ArrayIndexOutOfBoundsException("pos位置不合法" + pos);}                            //自定義異常}public void checkpos2(int pos){ //一個典型的受檢異常if(pos < 0 || pos >= useside){throw new ListEmptyException("獲取位置不合法" + pos);}}@Overridepublic void add(int pos,int data) {checkpos(pos);if(isFull()){grow();}                        //移動元素for(int i = useside - 1;i >= pos;i--){array[i+1] = array[i];}array[pos] = data;useside++;             //新加入了元素就更新計數}@Overridepublic boolean contains(int toFind) {for (int i = 0; i < array.length; i++) {if(array[i] == toFind){return true;}}return false;}@Overridepublic int indexOf(int toFind) {for (int i = 0; i < useside; i++) {//這里寫成了array.length會打印沒用的0if (array[i] == toFind){return i;}}return -1;             //-1肯定不屬于下標}@Overridepublic int get(int pos) {if(isEmpty()){throw new ArrayIndexOutOfBoundsException("數組是空的");}checkpos2(pos);return array[pos];}@Overridepublic void set(int pos, int value) {checkpos(pos);array[pos] = value;}@Overridepublic int size() {return array.length;}@Overridepublic void clear() {
//        for (int i = 0; i < array.length; i++) {
//            array[i] = 0/Null;
//        }useside = 0;}@Overridepublic void display() {//這里也是一樣,要寫useside而不是array.lengthfor (int i = 0; i < useside; i++) {System.out.print(array[i] + " ");}System.out.println();}@Overridepublic void remove(int toRemove) {int v = indexOf(toRemove);if(v == -1){System.out.println("找不到要刪除的值");return;             //終止代碼}for (int i = v; i < useside-1; i++) {array[i] = array[i+1];}useside--;}public static void main(String[] args) {MyarrayList x = new MyarrayList();x.add(0,9);       //在1位置添加一個9x.add(1,2);x.add(2,3);x.display();
//        try {
//            x.checkpos(100);
//        }catch (ArrayIndexOutOfBoundsException e){
//            e.printStackTrace();
//        }int c = x.get(1);System.out.println(c);x.remove(100);x.display();}}
public class ListEmptyException extends RuntimeException{public ListEmptyException() {}public ListEmptyException(String message) {super(message);}
}

自己實現過后有助于我們更好的理解順序表


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/919821.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/919821.shtml
英文地址,請注明出處:http://en.pswp.cn/news/919821.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

8.23打卡 DAY 50 預訓練模型+CBAM模塊

DAY 50: 預訓練模型與 CBAM 模塊的融合與微調 今天&#xff0c;我們將把之前學到的知識融會貫通&#xff0c;探討如何將 CBAM 這樣的注意力模塊應用到強大的預訓練模型&#xff08;如 ResNet&#xff09;中&#xff0c;并學習如何高效地對這些模型進行微調&#xff0c;以適應我…

北極圈邊緣生態研究:從數據采集到分析的全流程解析

原文鏈接&#xff1a;https://onlinelibrary.wiley.com/doi/10.1111/1744-7917.70142?afR北極圈邊緣生態研究&#xff1a;從數據采集到分析的全流程解析簡介本教程基于一項在俄羅斯摩爾曼斯克州基洛夫斯克市開展的長期生態學研究&#xff0c;系統講解如何對高緯度地區特定昆蟲…

Excel處理控件Aspose.Cells教程:使用Python將 Excel 轉換為 NumPy

使用 Python 處理 Excel 數據非常常見。這通常涉及將數據從 Excel 轉換為可高效操作的形式。將 Excel 數據轉換為可分析的格式可能非常棘手。在本篇教程中&#xff0c;您將學習借助強大Excel處理控件Aspose.Cells for Python&#xff0c;如何僅用幾行代碼將 Excel 轉換為 NumPy…

python 字典有序性的實現和OrderedDict

文章目錄 一、Python 3.7+ 字典有序性的驗證 二、如何在字典頭部插入鍵值對 方法 1:創建新字典(推薦) 方法 2:使用 `collections.OrderedDict`(適合頻繁頭部插入場景) 方法 3:轉換為列表操作(不推薦,效率低) 底層核心結構:雙數組哈希表 有序性的實現原理 與舊版本(…

JVM 調優全流程案例:從頻繁 Full GC 到百萬 QPS 的實戰蛻變

&#x1f525; JVM 調優全流程案例&#xff1a;從頻繁 Full GC 到百萬 QPS 的實戰蛻變 文章目錄&#x1f525; JVM 調優全流程案例&#xff1a;從頻繁 Full GC 到百萬 QPS 的實戰蛻變&#x1f9e9; 一、調優本質&#xff1a;性能瓶頸的破局之道&#x1f4a1; 為什么JVM調優如此…

基于TimeMixer現有腳本擴展的思路分析

文章目錄1. 加入數據集到data_loader.py和data_factory.py2. 參照exp_classification.py寫自定義分類任務腳本&#xff08;如exp_ADReSS.py&#xff09;3. 接一個MLP分類頭4. 嵌入指標計算、繪圖、保存訓練歷史的函數5. 開始訓練總結**一、可行性分析****二、具體實現步驟****1…

技術演進中的開發沉思-75 Linux系列:中斷和與windows中斷的區分

作為一名從 2000 年走過來的老程序員&#xff0c;看著 IT 技術從桌面開發迭代到微服務時代&#xff0c;始終覺得好技術就像老故事 —— 得有骨架&#xff08;知識點&#xff09;&#xff0c;更得有血肉&#xff08;場景與感悟&#xff09;。我想正是我的經歷也促成了我想寫這個…

【8位數取中間4位數】2022-10-23

緣由請輸入一個8位的十進制整數&#xff0c;編寫程序取出該整數的中間4位數&#xff0c;分別輸出取出的這4位數以及該4位數加上1024的得數。 輸入&#xff1a;一個整數。 輸出&#xff1a;兩個整數&#xff0c;用空格分隔-編程語言-CSDN問答 int n 0;std::cin >> n;std:…

mac電腦使用(windows轉Mac用戶)

首先&#xff0c;我們學習mac的鍵盤復制 command c 粘貼 command v 剪切 command xlinux命令行 退出中止 control c 退出后臺 control d中英文切換大小寫&#xff0c;按住左邊向上的箭頭 字母鼠標操作 滾輪&#xff1a;2個指頭一起按到觸摸板&#xff0c;上滑&#xff0c;…

項目中優惠券計算邏輯全解析(處理高并發)

其實這個部分的代碼已經完成一陣子了&#xff0c;但是想了一下決定還是整理一下這部分的代碼&#xff0c;因為最開始做的時候業務邏輯還是感覺挺有難度的整體流程概述優惠方案計算主要在DiscountServiceImpl類的findDiscountSolution方法中實現。整個計算過程可以分為以下五個步…

支持電腦課程、游戲、會議、網課、直播錄屏 多場景全能錄屏工具

白鯊錄屏大師&#xff1a;支持電腦課程、游戲、會議、網課、直播錄屏 多場景全能錄屏工具&#xff0c;輕松捕捉每一刻精彩 在數字化學習、娛樂與辦公場景中&#xff0c;高質量的錄屏需求日益增長。無論是課程內容的留存、游戲高光的記錄&#xff0c;還是會議要點的復盤、網課知…

LeetCode算法日記 - Day 20: 兩整數之和、只出現一次的數字II

目錄 1. 兩數之和 1.1 題目解析 1.2 解法 1.3 代碼實現 2. 只出現一次的數字II 2.1 題目解析 2.2 解法 2.3 代碼實現 1. 兩數之和 371. 兩整數之和 - 力扣&#xff08;LeetCode&#xff09; 給你兩個整數 a 和 b &#xff0c;不使用 運算符 和 - &#xff0c;計算并…

Spring AI 快速接入 DeepSeek 大模型

Spring AI 快速接入 DeepSeek 大模型 文章目錄Spring AI 快速接入 DeepSeek 大模型Spring AI 框架概述核心特性適用場景官網與資源AI 提供商與模型類型模型類型&#xff08;Model Type&#xff09;AI提供商&#xff08;Provider&#xff09;兩者的關系Spring AI 框架支持哪些 A…

jQuery 知識點復習總覽

文章目錄jQuery 知識點復習總覽一、jQuery 基礎1. jQuery 簡介2. jQuery 引入3. jQuery 核心函數二、選擇器1. 基本選擇器2. 層級選擇器3. 過濾選擇器4. 表單選擇器三、DOM 操作1. 內容操作2. 屬性操作3. CSS 操作4. 元素操作四、事件處理1. 事件綁定2. 事件對象3. 自定義事件五…

博客系統接口自動化練習

框架圖&#xff1a; 詳細代碼地址&#xff1a;gitee倉庫 博客系統接口自動化文檔請看文章頂部。

智慧礦山誤報率↓83%!陌訊多模態融合算法在礦用設備監控的落地優化

原創聲明&#xff1a;本文為原創技術解析文章&#xff0c;核心技術參數與架構設計引用自 “陌訊技術白皮書&#xff08;智慧礦山專項版&#xff09;”&#xff0c;算法部署相關資源適配參考aishop.mosisson.com平臺的陌訊視覺算法專項適配包&#xff0c;禁止未經授權的轉載與二…

Laravel 使用阿里云OSS S3 協議文件上傳

1. 安裝 S3 軟件包 composer require league/flysystem-aws-s3-v3 "^3.0" --with-all-dependencies2. 配置.env 以阿里云 OSS 地域華東2 上海為例: FILESYSTEM_DISKs3 //設置默認上傳到S3AWS_ACCESS_KEY_ID***…

UVM一些不常用的功能

uvm_coreservice_t是什么AI&#xff1a;在 UVM&#xff08;Universal Verification Methodology&#xff09;中&#xff0c;uvm_coreservice_t 是一個核心服務類&#xff0c;它扮演著UVM 框架內部核心服務的 “管理者” 和 “統一入口” 的角色。其主要作用是封裝并提供對 UVM …

怎么確定mongodb是不是鏈接上了?

現有mongosh鏈接了MongoDB,里面能操作,但是想python進行鏈接,因為代碼需要,現在測試下鏈接成功了沒有。如下: 要確認你的 MongoDB 連接是否成功,可以通過以下方法檢查: 1. 使用 list_database_names 方法【測試成功】 python import asyncioasync def test_connecti…

Unity 二進制讀寫小框架

文章目錄前言框架獲取與集成使用方法基本配置自動生成序列化方法實戰示例技術原理與優勢二進制序列化的優勢SJBinary的設計特點最佳實踐建議適用場景總結前言 在Unity開發過程中&#xff0c;與后臺交互時經常需要處理大型數據文件。當遇到一個近2MB的本地JSON文件需要解析為對…