#define LIST_INIT_SIZE 100 //线性表工作空间初始分配量
#define LISTINCREMENT 10 //每次增加的分配量
typedef struct{
int *elem; //整型的线性表 elem为地址
int length; //线性表当前长度
int listsize; //当前分配的存储容量 以sizeof(int)为单位
}SqList;
这是一个整型的线性表,elem是元素的地址,length表示线性表的当前长度。listsize表示当前分配的存储空间,在为线性表增加内容时,一旦超过大小,就再为其分配大小为LISTINCREMENT的空间。
接下来,需要创建一个空的表,为其开辟一个连续的空间。
bool InitList_Sq(SqList &L){
L.elem = (int *)malloc(LIST_INIT_SIZE * sizeof(int));
if(!L.elem){
/*exit (OVERFLOW);错误处理语句*/
cout<<"分配失败"<<endl;
return false;
}
L.length = 0;
L.listsize = LIST_INIT_SIZE;
return true;
}
以上是一个空的表,但是它已经有了地址。接下来是为其增加内容。
bool ListInsert_Sq(SqList &L,int i,int &q){
//在第i个位置插入新元素
//0 <= i <= L.length
if(i < 0 || i > L.length)return false;//可插入其它错误处理语句
/*如果空间不够 进行扩充*/
if(L.length >= L.listsize){
int *newbase;//创建临时指针,指向新分配的空间
newbase = (int *)realloc(L.elem,L.listsize+LISTINCREMENT * sizeof(int));//扩大空间
if(!newbase)return false;//可插入其它错误处理语句
L.elem = newbase;
L.listsize+=LISTINCREMENT;
}
int *temp;//创建临时指针
for(temp = L.elem + (L.length+1) * sizeof(int);temp > L.elem+i * sizeof(int);--temp){
*temp = *(temp-sizeof(int));
}
*( L.elem+i * sizeof(int) ) = q;
L.length++;
return true;
}
补充:realloc
指针名=(数据类型*)realloc(要改变内存大小的指针名,新的大小)。新的大小一定要大于原来的大小,不然的话会导致数据丢失!如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL
如果有足够空间用于扩大mem_address指向的内存块,则分配额外内存,并返回mem_address。
这里说的是“扩大”,我们知道,realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平。也就是说,如果原先的内存大小后面还有足够的空闲空间用来分配,加上原来的空间大小= newsize。那么就ok。得到的是一块连续的内存。
如果原先的内存大小后面没有足够的空闲空间用来分配,那么从堆中另外找一块newsize大小的内存。
并把原来大小内存空间中的内容复制到newsize中。返回新的mem_address指针。(数据被移动了)。
老块被放回堆上。
在增加的基础上进行修改,可以知道删除元素的代码。
bool ListDelete_Sq(SqList &L,int i){
if(i < 0 || i > L.length)return false;//可插入其它错误处理语句
int *temp;//创建临时指针
for(temp = L.elem+i * sizeof(int);temp <= L.elem + (L.length-1) * sizeof(int);++temp){
*temp = *(temp+sizeof(int));
}
L.length--;
return true;
}
但是,因为增加是往后移位,后位=前位,由此 循环是从后往前操作。删除则反之,往前移位,前位=后位,循环是递增的。