您的位置:首页 > 其它

第一部分 线性表的顺序存储(二)--动态分配

2011-04-12 00:35 561 查看
(二)线性表的动态分配顺序存储
1. 头文件及宏定义:
#include<stdio.h>
#include<stdlib.h>
#define LIST_INIT_SIZE 10 //初始分配量
#define LIST_INCREMENT 2 //分配增量
typedef int elemtype;
typedef enum
{
OK, //0

TRUE, //1

FALSE, //2

ERROR, //3

OVERFLOW, //4

}Status;
2.数据结构定义:
typedef struct
{
elemtype * elem; //存储空间基址

int length; //当前长度

int listsize; //当前分配的存储容量

}SqList;
3.基本操作:

/*构造一个空的顺序线性表*/
void InitList(SqList *L)
{
L->elem = (elemtype *)malloc(LIST_INIT_SIZE*sizeof(elemtype));
if(L->elem == NULL)
exit(OVERFLOW);
L->length = 0;
L->listsize = 0;
}
/*销毁顺序线性表*/
void DestroyList(SqList *L)
{
free(L->elem);
L->elem = NULL;
L->length = 0;
L->listsize = 0;
}
/*将线性表重置为空表*/
void ClearList(SqList *L)
{
L->length = 0;
}
/*判断线性表是否为空表,是返回true,否返回false*/
Status ListEmpty(SqList L)
{
if(L.length == 0)
return TRUE;
else
return FALSE;
}
/*返回顺序线性表中元素个数*/
int ListLength(SqList *L)
{
return L->length;
}
/*返回第i个元素的值到e*/
Status GetElem(SqList *L,int i,elemtype *e)
{
if(i<1 || i>L->length)
return ERROR;
*e = *(L->elem+i-1);
return OK;
}
/*若cur_e是L中的元素,且不是第一个,则用pre_e返回它的前驱*/
Status PriorElem(SqList *L,elemtype cur_e, elemtype * pre_e)
{
int i;
elemtype * p = L->elem+1;//从第二个元素开始判断

for(i=0;i<L->length-1;i++,p++)
if(*p == cur_e)
break;
if(i < L->length-1)
*pre_e = *--p;
else
return ERROR;
return OK;
}
/*若cur_e是L中的元素,且不是最后一个,则用next_e返回它的前驱*/
Status NextElem(SqList *L,elemtype cur_e, elemtype * next_e)
{
int i;
elemtype * p = L->elem;
for(i=0;i<L->length-1;i++,p++)//循环到倒数第二个元素

if(*p == cur_e)
break;
if(i < L->length-1)
*next_e = *++p;
else
return ERROR;
return OK;
}
/*在L中的i个位置之前插入一个新的元素e*/
Status ListInsert(SqList *L,int i,elemtype e)
{
elemtype *newbase,*q,*p;
if(i<1 || i>L->length+1)//listsize必须要比length大才能插入,且插入后必须要使元素的内存连续,所以i可以为length+1

return ERROR;
if(L->length == L->listsize)
{
newbase=(elemtype*)realloc(L->elem,(L->listsize+LIST_INCREMENT)*sizeof(elemtype));//重新分配内存,增加空间

if(!newbase)
exit(OVERFLOW);
L->elem = newbase;
L->listsize += LIST_INCREMENT;
}
q = L->elem+i-1;//q为插入的位置

for(p = L->elem+L->length-1;p>=q;p--)
*(p+1) = *p;//插入位置及之后的所有元素向表尾移动

*q = e; //插入e

++(L->length);
return OK;
}
/*删除L中的第i个数据元素,并用e返回其值*/
Status ListDelete(SqList *L,int i,elemtype *e)
{
elemtype *p,*q;
if(i<1 || i>L->length)
return ERROR;
q = L->elem+i-1; //要删除的位置

*e = *q;
p = L->elem+L->length;//表尾位置

for(++q;q<=p;++q)
*(q-1) = *q; //要删除位置之后的所有元素前移一位

L->length--;
return OK;
}

/*返回L中第一个与e满足关系compare()关系的元素的位置*/
int LocateElem(SqList *L,elemtype e,Status(*compare)(elemtype,elemtype))
{
int i = 1;
elemtype *p = L->elem;
while(i<=L->length && !compare(*p++,e))
++i;
if(i<=L->length)
return i;
else
return 0;
}

/*依次对L中的每一个元素调用函数visit(),来改变每一个元素的值。
对L中的元素用某个关系进行历遍*/

void ListTraverse(SqList *L,void(*visit)(elemtype *))
{
elemtype *p = L->elem;
int i;
for(i=1; i<=L->length; i++,p++)
visit(p);
}
以上操作中最后两个函数比较特殊,
int LocateElem(SqList *L,elemtype e,Status(*compare)(elemtype,elemtype))
void ListTraverse(SqList *L,void(*visit)(elemtype *))

特殊在这两个函数的参数 中都有一个 type1(* name)(type2,...,typen)这样的参数,这是用函数做参数的写法,其中name是一个指针形参,name所指向的的数据类型为 一个函数,这个函数的返回类型为type1,参数类型为type2,...,typen.
在调用该类函数时,只要把指定类型的函数的地址当作实参传入即可,也就是函数的名字,不需要加括号。
和形参compare匹配的实参类型,如myequle,IsSquare定义如下:
Status myequle(elemtype c1,elemtype c2)
{
//判断是否相等

if(c1 == c2)
return TRUE;
else
return FALSE;
}

Status IsSquare(elemtype a,elemtype b)
{
//判断a是否是b的平方关系,

if(a == b*b)
return TRUE;
else
return FALSE;
}
调用:
LocateElem(L,e,myequle);
LocateElem(L,e,IsSquare);
//和形参visit匹配的实参类型,如print,inc,定义如下:
void print(elemtype *c)
{
printf("%d",*c);
}
void inc(elemtype *c)
{
(*c)++;
}
4.归并:
void MergeList(SqList *La,SqList *Lb,SqList *Lc)
{
elemtype *pa,*pa_last,*pb,*pb_last,*pc;
pa = La->elem;
pb = Lb->elem;
Lc->listsize = Lc->length = La->length+Lb->length;
pc = Lc->elem = (elemtype*)malloc(Lc->listsize*sizeof(elemtype));
if(!pc)
exit(OVERFLOW);
pa_last = pa+La->length-1;
pb_last = pb+Lb->length-1;
while(pa<=pa_last && pb<=pb_last)
{
if(*pa<=*pb)
*pc++ = *pa++;
else
*pc++ = *pb++;
}
while(pa<=pa_last)
*pc++ = *pa++;
while(pb<=pb_last)
*pc++ = *pb++;

}
本文出自 “十年一剑” 博客,请务必保留此出处http://lhqvip.blog.51cto.com/2211973/542019
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: