简介:此数据结构定义为一个ArrayList结构体类型,维护了一个内部堆数组。通过realloc函数实现了数组容量自动扩充,每次扩充到原来的2倍。

通过函数指针实现了使用者根据自己的需求按条件按查找目标元素的功能,查找筛选函数需要使用者自行编写。

支持的主要操作:

追加Append

插入Insert

删除Delete

访问GetElement

写入SetElement

查找Find

FindAll

裁剪TrimToSize

销毁Destroy

/*
    file : ArrayList.h
*/

#ifndef _ARRAYLIST_H_
#define _ARRAYLIST_H_

    typedef int ElemType;              //存储的数据的类型     

    typedef int(*FindFunc)(ElemType);  //定义一个函数指针类型 FindFunc,作为查找函数 的类型

    typedef struct {

        ElemType *p_inner_arr;    //指向数组第一个元素的指针
        int length;          //表中实际元素个数
        int capacity;     //表的容量

    }ArrayList; 

void InitList(ArrayList* plist,int c);

void TrimToSize(ArrayList* plist) ;

int Insert(ArrayList* plist,ElemType x,int index);

void Append(ArrayList* plist,ElemType x);

int Delete(ArrayList* plist,ElemType* px,int index); 

ElemType GetElement(ArrayList*plist , int index);

void SetElement(ArrayList*plist , ElemType x, int index);

int IsEmpty(ArrayList *plist);

int Find(ArrayList *plist, FindFunc func); 
ArrayList* FindAll(ArrayList *plist, FindFunc func);

void Destroy(ArrayList*plist);

#endif

/*    file : ArrayList.cpp

*/ 

#include<stdlib.h>
#include "ArrayList.h"

/*初始化数组列表 

*/
void InitList(ArrayList* plist,int c)
{
  plist->capacity  = c;    //初始化容量
  plist->length = ;       //初始化实际长度 

  plist->p_inner_arr = (ElemType*)malloc(c * sizeof(ElemType)) ;
     //分配初始内存空间
    //假设这里malloc 总成功 

} 

/*裁剪多于的 没有存放数据的内存空间 。即length == capacity
*/
void TrimToSize(ArrayList* plist)
{
    ) return ;

    if(plist->length  <  plist->capacity)
    {        //realloc实现堆内存的大小调整,大小可增,也可以减,它会返回调整大小后的内存的新地址。重新赋值给p_inner_arr
        plist->p_inner_arr = (ElemType*)realloc(plist->p_inner_arr,plist->length*sizeof(ElemType));
        plist->capacity = plist->length;

    }
}

/*追加或者插入都可以
 增加失败返回 false
*/
int Insert(ArrayList* plist,ElemType x,int index)
{
    || index > (plist->length) ) //索引不合法
      ;

   if(plist->length  >=   plist->capacity)    //表已经饱和
   {
         plist->p_inner_arr = (ElemType*)realloc(plist->p_inner_arr,   plist->length**sizeof(ElemType));
        plist->capacity = plist->length*;
   } 

     ; i>=index ; --i )
    {
           plist->p_inner_arr[i+] = plist->p_inner_arr[i];        

     }
    plist->p_inner_arr[index] = x;    //插入 

    ++(plist->length);       //增加表长度 

    ;
}

/* 追加
*/
void Append(ArrayList* plist,ElemType x)
{
    if(plist->length  >=   plist->capacity)    //表已经饱和,无法容纳
     {
         plist->p_inner_arr = (ElemType*)realloc(plist->p_inner_arr,   plist->length**sizeof(ElemType));
         plist->capacity = plist->length*;
     } 

    plist->p_inner_arr[plist->length] = x;

    ++(plist->length); 

    return ;

} 

/*删除某个元素
删除失败返回false
*/
int Delete(ArrayList* plist,ElemType* px,int index)
{
     )  ;

      || index > (plist->length-))   ;

     if(px!=NULL) *px = (plist->p_inner_arr)[index];
     /*数据结构的使用者可以选择是否需要保存
       这个被删除的元素,不需要则传入NULL
    */

      ; ++i)  //前移
     {
        plist->p_inner_arr[i] = plist->p_inner_arr[i+];     

    }

     --(plist->length);
     ;

}

ElemType GetElement(ArrayList*plist , int index)
{
    return plist->p_inner_arr[index];

}

void SetElement(ArrayList*plist , ElemType x, int index)
{
     || index> plist->length ) return ;

    plist->p_inner_arr[index] = x;

}

//状态判断
int IsEmpty(ArrayList *plist)
{
   ;
}

/*按条件查找
  条件函数由使用者自行编写,这个函数接受一个ElemType类型参数,并返回1  or  0
  一旦找到了符合条件的元素,就返回它的索引,没找到,则返回 -1
*/
int Find(ArrayList *plist, FindFunc func)
{
    ; i<plist->length ; ++i)
    {
        if(func(plist->p_inner_arr[i]))
          return i;

    }

    ;

}

/* 按条件查找所有符合的元素 

*/
ArrayList* FindAll(ArrayList *plist, FindFunc func)
{
    ArrayList*tlist ;    //新建一个Arraylist对象,用来保存符合条件的元素
    InitList(tlist,) ;

    ; i<plist->length; ++i)
    {
        if(func(plist->p_inner_arr[i]))
          Append(tlist,plist->p_inner_arr[i]);

    }

    )    //没有找到任何符合要求的元素
    {
        Destroy(tlist);
        return NULL;
    }

    TrimToSize(tlist);

    return tlist;
}

void Destroy(ArrayList*plist)
{
    free(plist->p_inner_arr);

    plist->p_inner_arr = NULL;
    plist->length=;
    plist->capacity=;
}

心得:

1、还是面对对象好,主要优势很明显:数据对象的自描述性和自操作性,也就是一个数据的属性和操作都在"自己身"上找到,还有封装会使数据结构更加完美,安全。

2、数据结构需要的通用性要好,而C本身不支持泛型编程,但是在编写代码的时候可以优化代码的通用性,这样使用不同目标数据类型时,只需要做很少的修改。

3、还是C语言写起来有感觉些,简洁,自由,哈哈。

变长数组列表ArrayList的更多相关文章

  1. C++内存分配及变长数组的动态分配

    //------------------------------------------------------------------------------------------------ 第 ...

  2. oracle:变长数组varray,嵌套表,集合

    创建变长数组类型 ) );  这个变长数组最多可以容纳两个数据,数据的类型为 varchar2(50) 更改元素类型的大小或精度 可以更改变长数组类型和嵌套表类型 元素的大小. ALTER TYPE ...

  3. C99新增内容之变长数组(VLA)

    我们在使用多维数组是有一点,任何情况下只能省略第一维的长度.比如在函数中要传一个数组时,数组的行可以在函数调用时传递,当属数组的列却只能在能被预置在函数内部.看下面一个例子: #define COLS ...

  4. GCC 中零长数组与变长数组

    前两天看程序,发现在某个函数中有下面这段程序: int n; //define a variable n int array[n]; //define an array with length n 在 ...

  5. C99新特性:变长数组(VLA)

    C99标准引入了变长数组,它允许使用变量定义数组各维.例如您可以使用下面的声明: ; ; double sales[rows][cols]; // 一个变长数组(VLA) 变长数组有一些限制,它必须是 ...

  6. PL/SQL — 变长数组

    PL/SQL变长数组是PL/SQL集合数据类型中的一种,其使用方法与PL/SQL嵌套表大同小异,唯一的区别则是变长数组的元素的最大个数是有限制的.也即是说变长数组的下标固定下限等于1,上限可以扩展.下 ...

  7. PL/SQL 嵌套表变长数组和索引表[转]

    关于PL/SQL中这三种数组的介绍,不想写了.转一篇日志吧…… 链接:http://www.blogjava.net/decode360/archive/2008/08/08/280825.html ...

  8. c语言,变长数组

    下面这个结构体,可以在malloc的时候指定数据data的长度,这样的形式就是变长数组:typedef struct{ int data_len; char data[0];//或char data[ ...

  9. C99中的变长数组(VLA)

    处理二维数组的函数有一处可能不太容易理解,数组的行可以在函数调用的时候传递,但是数组的列却只能被预置在函数内部.例如下面这样的定义: #define COLS 4 int sum3d(int ar[] ...

随机推荐

  1. swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程

    swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 1.2.3  注册非免费苹果账号swift语言注册非免费苹果账号iOS游戏框架Sprite Kit基础教程 免费的苹果账号在 ...

  2. Ajax本地跨域问题

    问题:打开本地html文件时,,报错如下 Cross origin requests are only supported for protocol schemes: http, data,chrom ...

  3. 用indexOf判断设备是否是PC端?

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. 海贼王之——梦想音乐

      相信和很多海粉一样,对伙伴的关照和战斗,是相当地震撼.   好东西时不时地听一下,然后感受那种刷新全身表层细胞,触电...:   音乐链接: http://v.youku.com/v_show/i ...

  5. 【BZOJ】3319: 黑白树

    http://www.lydsy.com/JudgeOnline/problem.php?id=3319 题意:给一棵n节点的树(n<=1e6),m个操作(m<=1e6),每次操作有两种: ...

  6. sqlserver行列转换

    sqlserver行转列 --创建行转列表及插入数据 create table tb_RowConvertToColumn ( username ) null, course ) null, scor ...

  7. Git补丁

    引子: 上班有问题没有解决,在家里搞定了,于是把改动打成一个补丁,明天应用到公司的工作电脑上.(以下内容转自别处) 1.创建补丁,比如把最新的两次提交纪录转化为补丁文件,可以用如下命令: git fo ...

  8. hdu A计划

    这道题是一道bfs的题目,因为题目中给的数据很小,所以可以采用优先队列的方式来简化处理.这道题在搜索的过程中要注意map1的不同层次的转换,即对'#'的理解.之前wa了两次是因为我考虑了如果上下两层对 ...

  9. SVN的学习和安装

    SVN分为服务器版本和客户端版本 服务器:VISUALSVN SERVER https://www.visualsvn.com/server/download/ 安装和配置(都很简单,只要不断的下一步 ...

  10. 【转】C#文件操作大全

    文件与文件夹操作主要用到以下几个类: 1.File类: 提供用于创建.复制.删除.移动和打开文件的静态方法,并协助创建 FileStream 对象. msdn:http://msdn.microsof ...