欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java版C語言版簡單使用靜態(tài)語言實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的方法

 更新時(shí)間:2017年10月20日 11:03:47   作者:defmain  
本文給大家分享java版和C語言版簡單使用靜態(tài)語言實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧

動(dòng)態(tài)語言相對于靜態(tài)語言的一個(gè)優(yōu)勢,就是數(shù)組可以不需要預(yù)先確定大小,對于一些數(shù)組長度不確定的場景下是非常有用的。像PHP,只需要聲明一下數(shù)組 $arr = array() 然后就可以直接 $arr[] = 1,$arr[] = 2,$arr[] = 3...這樣一直加元素了,刪除一個(gè)元素就直接使用unset($arr[1]),元素的空間就被釋放了,而C和JAVA原生的數(shù)組就沒有這么方便,聲明的時(shí)候就必須先預(yù)先確定長度,由編譯器分配相應(yīng)的內(nèi)存空間。不過通過一些巧妙的做法,也是可以實(shí)現(xiàn)一樣的功能的,這也是本文的主要內(nèi)容。

JAVA版

JAVA自帶了一個(gè)集合類ArrayList,可以實(shí)現(xiàn)動(dòng)態(tài)數(shù)組的功能,相比原生的數(shù)組,使用起來非常方便。在閱讀Tomcat源碼的時(shí)候,發(fā)現(xiàn)出于性能考慮使用了原生的數(shù)組,而沒有直接使用原生的ArrayList,自己實(shí)現(xiàn)了一個(gè)動(dòng)態(tài)數(shù)組,下面的這個(gè)實(shí)現(xiàn)就是直接從Tomcat的源碼借鑒過來的。

實(shí)現(xiàn)思路

動(dòng)態(tài)添加元素

初始化一個(gè)數(shù)組,大小固定。

獲取源數(shù)組的大小,在方法區(qū)里面申請一個(gè)比原有數(shù)組大1位的數(shù)組。

關(guān)鍵的內(nèi)容是,調(diào)用System.arraycopy(src, 0, dest, 0, src.length),從src的0位復(fù)制src.length位到dest的0位,這里用系統(tǒng)自帶的方法比較方便,也可以自己寫一個(gè)循環(huán)進(jìn)行復(fù)制。

把要添加的元素放到新數(shù)組的最后一位。

返回元素,把新數(shù)組的指針復(fù)制到原數(shù)組變量,JAVA的數(shù)組是引用型的,執(zhí)行 src=dest 后,兩者實(shí)際上是指向同一個(gè)內(nèi)存地址。

動(dòng)態(tài)刪除元素

初始化一個(gè)數(shù)組,大小固定。

在方法區(qū)申請一個(gè)比原生數(shù)組小一位的數(shù)組

從index位開始,把后面的元素同時(shí)往前移動(dòng)一位,覆蓋要?jiǎng)h除的元素。

返回元素,把改變原數(shù)組的指向到新數(shù)組

package demo;
import java.util.Arrays;
public class DiyArrayListDemo {
  public static void main(String[] args){
    int[] arr = {5,8,10};
    System.out.println(Arrays.toString(arr));//=>[5, 8, 10]
    arr = DiyArrayList.add(arr, 15);
    arr = DiyArrayList.add(arr, 20);
    arr = DiyArrayList.add(arr, 25);
    System.out.println(Arrays.toString(arr)); //=>[5, 8, 10, 15, 20, 25]
    arr = DiyArrayList.remove(arr, 1);
    System.out.println(Arrays.toString(arr)); //=>[5, 10, 15, 20, 25]
  }
}
class DiyArrayList{
  public static int[] add(int[] src,Integer newData){
    //定義目標(biāo)數(shù)組,長度是比原始數(shù)組多一位
    int[] dest = new int[src.length+1];
    //從src的0位開始,復(fù)制到dest的0位置,復(fù)制長度是src的長度
    System.arraycopy(src, 0, dest, 0, src.length);
    //填充最后一位的值
    dest[src.length] = newData;
    return dest;
  }
  public static int[] remove(int[] src,Integer index){
    //定義目標(biāo)數(shù)組,長度是比原始數(shù)組少一位
    int[] desc = new int[src.length-1];
    for(int i=0; i<src.length; i++){
      //超過索引index的數(shù)據(jù)往前移動(dòng)一位
      if(i > index){
        desc[i-1] = src[i];
      }else{
        desc[i] = src[i];
      }
    }
    return desc;
  }
}

C語言版

C語言中實(shí)現(xiàn)動(dòng)態(tài)數(shù)組相對比較復(fù)雜一點(diǎn),因?yàn)镃語言要對指針,內(nèi)存進(jìn)行操作。開始之前需要定義一個(gè)結(jié)構(gòu)體arrayList和結(jié)構(gòu)體變量ArrayList,里面包含兩個(gè)數(shù)組,一個(gè)是int類型的指針,用來指向存儲(chǔ)int型數(shù)組的內(nèi)存,還有一個(gè)count,用來記錄數(shù)組的長度,因?yàn)橥ㄟ^malloc(),realloc()進(jìn)行動(dòng)態(tài)內(nèi)存分配(程序執(zhí)行的時(shí)候分配),用sizeof()是無法獲取到正確的內(nèi)存長度的,所以必須要定義一個(gè)變量count去記錄到底向系統(tǒng)申請了多少內(nèi)存。為什么需要用malloc而不是像JAVA那樣直接用new int[] 來創(chuàng)建一個(gè)數(shù)組呢?這就涉及了JAVA和C內(nèi)存分配的一個(gè)區(qū)別,JAVA方法里面的數(shù)組是存放在堆中,而C函數(shù)里面的數(shù)組分配的內(nèi)存是存放在棧中的,函數(shù)執(zhí)行結(jié)束,數(shù)組的內(nèi)存空間就會(huì)被釋放,因此需要用malloc從棧申請空間。

實(shí)現(xiàn)思路

動(dòng)態(tài)添加元素

通過realloc() 重新申請一個(gè)新的內(nèi)存空間,空間比當(dāng)前數(shù)組的大一個(gè)int長度,通過int*類型的指針指向該空間。

把數(shù)據(jù)放在數(shù)組的最后一位。

把記錄的數(shù)組長度進(jìn)行++操作。

動(dòng)態(tài)刪除元素

判斷函數(shù)傳入的index是否有效。

把大于index的數(shù)組數(shù)據(jù)往前移動(dòng)一個(gè)索引。

重新申請空間,數(shù)組長度縮減一個(gè)int長度。

把記錄的數(shù)組長度進(jìn)行--操作。

demo.h

//定義一個(gè)結(jié)構(gòu)體,data里面儲(chǔ)存的是int類型指數(shù)組,count存儲(chǔ)的是數(shù)組的長度
typedef struct arrayList {
  int* data;
  int count;
} ArrayList;
void initArrayList(ArrayList* list);
void arrayListAdd(ArrayList* list, int data);
void arrayListRemove(ArrayList* list, int index);
void printAll(ArrayList list);
demo.c
#include <stdio.h>
#include <stdlib.h>
#include "test.h"
int main() {
  ArrayList arrayList;
  initArrayList(&arrayList);
  arrayListAdd(&arrayList, 10);
  arrayListAdd(&arrayList, 13);
  arrayListAdd(&arrayList, 15);
  arrayListRemove(&arrayList, 2);
  printAll(arrayList);
}
/********************************
函數(shù)名:initArrayList()
功能:初始化ArrayList結(jié)構(gòu)體
輸入:ArrayList類型結(jié)構(gòu)體指針
輸出:無
*/
void initArrayList(ArrayList* arrayList) {
  arrayList->data = NULL;
  arrayList->count = 0;
}
/*******************************
函數(shù)名:arrayListAdd()
功能:添加數(shù)據(jù)到ArrayList類型結(jié)構(gòu)體里面的數(shù)組
輸入:ArrayList類型結(jié)構(gòu)體指針,int類型數(shù)據(jù)
輸出:無
*/
void arrayListAdd(ArrayList* list, int data) {
  int count = list->count;
  //重新申請空間,空間比現(xiàn)在的長度大1個(gè)int長度
  int* newDataArr = (int*)realloc(list->data,sizeof(int) * (++count));
  if (newDataArr != NULL) {
    list->data = newDataArr;
    list->data[count - 1] = data;
    list->count++;
  }
  else {
    puts("申請空間失敗");
  }
}
/*******************************
函數(shù)名:arrayListRemove()
功能:根據(jù)index刪除ArrayList類型結(jié)構(gòu)體里面的數(shù)組元素
輸入:ArrayList類型結(jié)構(gòu)體指針,int類型索引
輸出:無
*/
void arrayListRemove(ArrayList* list, int index) {
  if (index > list->count) {
    puts("超出數(shù)組索引");
    exit(1);
  }
  //把大于index的數(shù)組數(shù)據(jù)往前移動(dòng)一個(gè)索引
  for (int i = 0; i < list->count; i++) {
    if (i > index) {
      list->data[i - 1] = list->data[i];
    }
  }
  int count = list->count;
  //重新申請空間,數(shù)組長度縮減一個(gè)int長度
  int *newDataArr = realloc(list->data, sizeof(int) * (--count));
  if (newDataArr != NULL) {
    list->data = newDataArr;
    list->count = count;
  }
  else {
    puts("申請空間失敗");
  }
}
/********************************
函數(shù)名:打印所有數(shù)組
輸入:ArrayList類型結(jié)構(gòu)體
*/
void printAll(ArrayList list) {
  for (int i = 0; i < list.count; i++) {
    printf("%d \r\n", list.data[i]);
  }
}

總結(jié)

以上所述是小編給大家介紹的Java簡單使用靜態(tài)語言實(shí)現(xiàn)動(dòng)態(tài)數(shù)組,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 關(guān)于SpringBoot使用@ExceptionHandler注解局部異常處理

    關(guān)于SpringBoot使用@ExceptionHandler注解局部異常處理

    這篇文章主要介紹了關(guān)于SpringBoot使用@ExceptionHandler注解局部異常處理,SpringBoot提供了多種方式來處理異常,在本文中,我們將介紹SpringBoot中的@ExceptionHandler注解,演示如何使用它進(jìn)行局部異常處理
    2023-07-07
  • Spring Boot Admin 的使用詳解

    Spring Boot Admin 的使用詳解

    這篇文章主要介紹了Spring Boot Admin 的使用詳解,Spring Boot Admin 用于監(jiān)控基于 Spring Boot 的應(yīng)用,有興趣的可以了解一下
    2017-09-09
  • Java多線程ForkJoinPool實(shí)例詳解

    Java多線程ForkJoinPool實(shí)例詳解

    這篇文章主要介紹了Java多線程ForkJoinPool實(shí)例詳解,涉及forkjoin框架的相關(guān)內(nèi)容,需要的朋友可以參考下。
    2017-09-09
  • Java中Map與對象之間互相轉(zhuǎn)換的幾種常用方式

    Java中Map與對象之間互相轉(zhuǎn)換的幾種常用方式

    在Java中將對象和Map相互轉(zhuǎn)換是常見的操作,可以通過不同的方式實(shí)現(xiàn)這種轉(zhuǎn)換,下面這篇文章主要給大家介紹了關(guān)于Java中Map與對象之間互相轉(zhuǎn)換的幾種常用方式,需要的朋友可以參考下
    2024-01-01
  • 學(xué)生視角手把手帶你寫Java?線程池初版

    學(xué)生視角手把手帶你寫Java?線程池初版

    作者是一個(gè)來自河源的大三在校生,以下筆記都是作者自學(xué)之路的一些淺薄經(jīng)驗(yàn),如有錯(cuò)誤請指正,將來會(huì)不斷的完善筆記,幫助更多的Java愛好者入門
    2022-03-03
  • 詳解使用Spring Security進(jìn)行自動(dòng)登錄驗(yàn)證

    詳解使用Spring Security進(jìn)行自動(dòng)登錄驗(yàn)證

    本篇文章主要介紹了詳解使用Spring Security進(jìn)行自動(dòng)登錄驗(yàn)證,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2017-09-09
  • 如何解決java:錯(cuò)誤:無效的源發(fā)行版:16

    如何解決java:錯(cuò)誤:無效的源發(fā)行版:16

    這篇文章主要介紹了如何解決java:錯(cuò)誤: 無效的源發(fā)行版:16問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • Mybatis動(dòng)態(tài)SQL的實(shí)現(xiàn)示例

    Mybatis動(dòng)態(tài)SQL的實(shí)現(xiàn)示例

    這篇文章主要介紹了Mybatis動(dòng)態(tài)SQL的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題

    SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題

    這篇文章主要介紹了SpringBoot整合Mybatis,解決TypeAliases配置失敗的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • jar包手動(dòng)添加到本地maven倉庫的步驟詳解

    jar包手動(dòng)添加到本地maven倉庫的步驟詳解

    在寫程序的過程中,有時(shí)候會(huì)遇到私服里沒有需要的jar包的情況,這時(shí)候我們就可以手動(dòng)導(dǎo)入jar包到本地倉庫進(jìn)行使用,下面這篇文章主要給大家介紹了關(guān)于jar包手動(dòng)添加到本地maven倉庫的相關(guān)資料,需要的朋友可以參考下
    2022-08-08

最新評論