【线性表】变长数组列表

 简介:此数据结构定义为一个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 = 0;       //初始化实际长度 
  
  plist->p_inner_arr = (ElemType*)malloc(c * sizeof(ElemType)) ;
     //分配初始内存空间 
    //假设这里malloc 总成功 
   
} 


/*裁剪多于的 没有存放数据的内存空间 。即length == capacity 
*/
void TrimToSize(ArrayList* plist) 
{
    if(plist->length==0) return ;
    
    if(plist->length  <  plist->capacity)
    {
        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)
{
   if(index<0 || index > (plist->length) ) //索引不合法 
      return 0;
   
   if(plist->length  >=   plist->capacity)    //表已经饱和
   {
           plist->p_inner_arr = (ElemType*)realloc(plist->p_inner_arr,   plist->length*2*sizeof(ElemType)); 
        plist->capacity = plist->length*2;
   } 
   
    
    for(int i = plist->length-1 ; i>=index ; --i ) 
    {
           plist->p_inner_arr[i+1] = plist->p_inner_arr[i];        
         
     }
    plist->p_inner_arr[index] = x;    //插入 
                                  
    ++(plist->length);       //增加表长度 
                                  
    return 1; 
}


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



/*删除某个元素
删除失败返回false
*/ 
int Delete(ArrayList* plist,ElemType* px,int index)
{
     if(plist->length==0)  return 0;
     
     if(index<0 || index > (plist->length-1))   return 0;
     
     if(px!=NULL) *px = (plist->p_inner_arr)[index];
     /*数据结构的使用者可以选择是否需要保存
       这个被删除的元素,不需要则传入NULL
    */
     
     for(int i=index; i<plist->length-1 ; ++i)  //后移 
     {
        plist->p_inner_arr[i] = plist->p_inner_arr[i+1];     
   
    }
     
     --(plist->length);
     return 1;
     
    
}



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

void SetElement(ArrayList*plist , ElemType x, int index)
{
    if(index<0 || index> plist->length ) return ;
    
    plist->p_inner_arr[index] = x;
     
}




//状态判断 
int IsEmpty(ArrayList *plist)
{
   return plist->length == 0;
}



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

/* 按条件查找所有符合的元素 
    
    
*/
ArrayList* FindAll(ArrayList *plist, FindFunc func)
{
    ArrayList*tlist ;    //新建一个Arraylist对象,用来保存符合条件的元素 
    InitList(tlist,5) ;
    
    for(int i=0; i<plist->length; ++i)
    {
        if(func(plist->p_inner_arr[i]))
          Append(tlist,plist->p_inner_arr[i]);

    }
    
    if(tlist->length == 0)    //没有找到任何符合要求的元素 
    {
        Destroy(tlist);
        return NULL;
    }
    
    
    
    TrimToSize(tlist);
    
    return tlist;
}
    
    
    



void Destroy(ArrayList*plist)
{
    free(plist->p_inner_arr);
    
    plist->p_inner_arr = NULL;
    plist->length=0;
    plist->capacity=0;
}

 

 

心得:

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

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

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

 

 

    

 

你可能感兴趣的:(【线性表】变长数组列表)