JAVA中ArrayList的底层基本实现

来源:互联网 发布:ec软件使用 编辑:程序博客网 时间:2024/05/16 01:19
/* 我不想做码农,那就学学算法吧*//*    1.实现一个简单的Arraylist。      Arraylist的功能有如下      a.增加元素     Ok      b.查找元素           c.修改元素      4.查找元素     而且他是有下标的,也就是类似操作一个数组.     线性表这里面我们暂时不使用动态扩容了,在链表的时候我们在采取动态扩容的方法*/#define MAX_SIZE 103 //设置最大存储容量为20#define INIT_SIZE 5 //初始的存储容量为5typedef int Element;// 设置一下变量的类型.以后用Element来代替int,作用我也不是很清楚待查...#include <stdio.h>#include <stdlib.h>/*     代码步骤分析    1.我们首先要创建一个线性表,那么我们就需要去查看      我们的链表是否存在 a.存在我们就把链表取出来,之后继续下面的操作 b.不存在那么就需要我们去创建一个链表      在这之前我们需要了解一些 东西 指针的操作        eg:  int *p;           int a=10;           p=&a; 把a的地址给了p,p就是a的地址,之后采用*运算符去把地址里面的值取出来           我们来实践一下    想到还是指针操作的方便*/typedef struct{    /*         这里面的参数就值得商议了        首先一定要有一个element 类型的指针了,用来存储变量的信息        其次,还需要知道现在存储的是第几个值.以及        (数据结构与我们评出所基础的数组有一点点不同.是给人看的.不能从0开始查)    */    Element *data;    int length;    int maxSize;//当前存储的最大容量    /*         如果说像我这么定义的话那么只能够存储一位整数.    */}Sql_L;    /*         写到这里发现了一个问题.我们可以在一开始main函数刚刚进来的时候,就先调用这个函数        判断的方法判断他的长度是否为0        写到这里我也有一些疑惑(可能是学java写太长时间了.都不清楚c语言中能不能调用.length...- -!)        数组以'\0'为结束标志,一般可以通过此方法求出数组(有用数据的)长度,数组长度是定义的,一般不用求的。        当然也可以通过数组内存空间大小来求数组长度,        如:sizeof函数也可以求数组大小        我们需要去加一个函数用去求数组的长度的函数getLength();        下面我们去写如何初始化一个线性表    *///实现线性表的初始化int initArrayList(Sql_L *ArrayList )//好像传出的需要是这个类型的数据{    //算了,既然用到了初始化线性表那么还是 来写一个动态赋予吧.不是动态赋予的话很简单 简单的查了一下 可以new        ArrayList->data = (Element *)malloc(sizeof(Element *)*INIT_SIZE);        if(ArrayList->data == NULL)        {            printf("初始化失败,程序即将推出!");            exit(0);        }        else        {            ArrayList->length = 0;            ArrayList->maxSize =MAX_SIZE;             printf("初始化成功!");            return 1;//这样传出的话,传出的是一个地址!        }}//获取线性表的长度int getLength(Sql_L *L){    /*思考我们该如何去确定一个指针里面到底有没有值      如果说是一个数组的花那么很好办 有两种方法      作为一个指针可以用.length么?显然是不可以的      好吧!他有.length方法    */    return L->length;}/*     E remove(int index)     移除此列表中指定位置上的元素。     boolean remove(Object o)     移除此列表中首次出现的指定元素(如果存在)。 *///第一种移除方式int removeElementByIndex(Sql_L *L){    //移出的下标,我们需要去判断一下    int index;    int i;    //我们按照下表进行演示    printf("请输入你要删除的位置:");    scanf("%d",&index);    if(index < 0 || index > L->length-1)    {        return -1;    }    //如果下标符合操作的话,下面还是移动的操作,不过这次是向前移动了    for(i = index; i < L->length-1 ; i++)    {        (L+i)->data=(L+i+1)->data;    }    L->length--;    return 1;}//  删除该元素第一次出现的位置int removeElementByIndexFirst(Sql_L *L){    //移出的下标,我们需要去判断一下    int index;    int value;    int i;    printf("请输入你要删除的元素:(删除第一次出现的)");    scanf("%d",&value);    //我们按照下表进行演示    for(i = 0; i < L->length; i++)    {        if((L+i)->data == value)        {            //当拿到第一个出现的下标就退出            index = i;break;        }    }    //如果下标符合操作的话,下面还是移动的操作,不过这次是向前移动了    for(i = index; i < L->length-1 ; i++)    {        (L+i)->data=(L+i+1)->data;    }    L->length--;    return 1;}//插入元素(尾部)int insertElement(Sql_L *L){    //下节课再说.我们来听一首歌先    //加到后面我们不用去考虑那么多.直接怼就可以不过我要知道到底加到第几个    //我就是想知道而已.然后回一下汇编 看能不能找到我刚刚插进去的数字    int local = L->length;    if(L->length >=20)    {        printf("容量已经满了,需要扩容了!");        /*             下面应该写一个动态扩容的函数        */        return -1;    }    else    {        int element;//初始化 与 不初始化的区别在哪里?        printf("请输入你要插入的数字:(选择的第一种很方式为追加到元素的尾部)");        /* 果然这个里面出错了*/        scanf("%d",&element);        printf("element的值位:%d",element);        (L+local)->data=element;        L->length++;        return 1;    }        //我还是需要判断下长度的}/* 下面写一下线性表中的set 函数        set(int index, E element)         用指定的元素替代此列表中指定位置上的元素。 *///修改指定下标元素的值int setElement(Sql_L *L){    int local;    int value;    //替换的位置我们需要 判断一下    printf("请输入你要替换的位置:");    scanf("%d",&local);    printf("请输入你要替换的值:");    scanf("%d",&value);    if(local < 0 || local > L->length - 1)    {        return -1;    }    //没有什么难的.说白了 就是做一个值得替换    (L+local)->data = value;    return 1;}//插入一个特定位置的元素int insertElementByLocal(Sql_L *L){    /* 我们先需要判断他插入的位置合理不合理*/    int i = 0;    int local_Length = 0;    int value = 0;    printf("请输入你要插入的位置:\n");    scanf("%d",&local_Length);    printf("请输入你要插入的值:\n");    scanf("%d",&value);    if(local_Length < 0 || local_Length > L->length) // 当插入的位置等于最大长度的话是可以插入的.类似于直接插入到线性表的最后面    {        //在我的这里面1代表 程序没问题 0代表程序出错        return -1;    }    /* 插入得时候这个数组长度.我是先加一 还是后加一.这是一个问题.       c语言中好像存在这样一种机制可以跨越直接给地址赋值       但问题是:会不会影响其他的内容造成内存的溢出,好在       指针就是一个类似于数组的玩意以'\0'作为判断他是否是最后一个       所以我们选择先插入后面再++       一会在测试一下,如果先加了会怎么样.      注释:插入的位置我们让他以计算机的思维吧    */    //从最后面依次向前移动    //去测试一下数组的移动    //还是先加1把    L->length++;    for(i=L->length-1;i > local_Length;i--)    {        (L+i)->data = (L+(i-1))->data;    }    (L+local_Length)->data=value;    return 1;}/* 下面的元素用于查找元素是否存在    如果存在则返回他的下标    如果不存在则返回-1*///搜索元素的下标存在不存在int searchElement(Sql_L *L){    int Element;    int i;    printf("请输入你要查找的元素:\n");    scanf("%d",&Element);    for( i = 0; i < L->length; i++)    {        if((L+i)->data == Element)        {            //返回的是下标            printf("查找到的下标为:%d",i);            return i;        }    }        return -1;}//遍历线性表void prior(Sql_L *L){    //先获取他的长度        int i ;        for(i = 0; i < L->length; i++)        {            printf("当前的长度为:%d",L->length);            printf("\n");            /* 需要将一个首地址传过来*/            printf("当前的数值为:%d",(L+i)->data);        //  *(L.data+i-1)        }}/* 把所有写好的函数都放在上面这样并无耽误事.不然以后还需要在上面声明一下神烦.*/int main(){    /*刚刚写好初始化的部分问题就来了.我竟然不知道如何去使用这个*ArrayList变量,先拿过来直接用试试*/     //我是地址你也是地址,咱俩可以直接用地址进行交互没毛病吧!    /* 接下来如何去连接这是一个问题 */    /* 调用出错,我们应考虑 怎么把定义过的结构体类型拿过来用以及 在动态创键一个数组的时候到底该返回什么*/    Sql_L *ArrayList;    int length;    int choice;    int status;    //标志变量    int FLAG = 1;    int insertElement_status;    int backStatus = 1;    //这个步骤是用来给线性表做初始化的    initArrayList(&ArrayList);    while(FLAG)    {        printf("请输入你的选择:");        scanf("%d",&choice);        switch(choice)        {               // 1我们用来显示插入到尾部的操作            case 1: status =  insertElement(&ArrayList);break;            // 2我们用来做固定位置的插入            case 2: status =  insertElementByLocal(&ArrayList);break;            // 3我们用来描述关于数据的查找.            case 3: status =  searchElement(&ArrayList);break;            //用于替换特定位置特定的值            case 4: status = setElement(&ArrayList);break;            //删除元素按照数组下标进行删除            case 5:status = removeElementByIndex(&ArrayList);break;            //删除元素第一次出现的指定的元素            case 6: status = removeElementByIndexFirst(&ArrayList);break;            // 8我们用来描述线性表的遍历            case 8: prior(&ArrayList);break;        }        if(status == -1)        {            printf("操作出了问题,请审查!");        }        else        {            printf("继续操作请输入任意数字(输入0则退出):");            scanf("%d",&FLAG);        }        getchar();    }    /* 传入的地址出现了问题 */    /* 插入数据*//*  if(insertElement_status == 1)    {        printf("添加成功!");    }    else    {        printf("添加数据失败!");    }*/    /*    while(backStatus)    {           backStatus =  insertElementByLocal(&ArrayList);        prior(&ArrayList);    }*/    /* 接下来是遍历函数*/    printf("欢迎下次使用!");    /*        先去实现他的基本功能         a.增加功能 按照下标 (这里面的元素是可以重复的)(二笔了.说错了 咱们全部按照JAVA中的Arraylist去实现 查看下api)        boolean add(E e)           将指定的元素添加到此列表的尾部。         void add(int index, E element)           将指定的元素插入此列表中的指定位置。         先来实现这两个功能        b.删除功能 删除下标        c.修改功能        d.查找功能    */    /*         第一步:我们先去考虑 先去测量 这个结构的长度 @@@@1    */    //我就是想看一下我成功了没有!    /* 一个比较大的疑问 是不是我们全局操作的就是这一个对象*/    /* 下面这个函数为 测试 添加的数据是否成功的        以及再写一个方法,用来遍历我们的数据    */    return 0;}
原创粉丝点击