線性表與13個基本操作的實現
一、巨集定義解釋
ElemType :線性表資料元素資料型別
LIST_INIT_SIZE : 線性表初始資料元素容量
Status :函式返回值(一般替換int型)
error :0
INFEASIBLE :0
OK :0
二、線性表結構體
typedef struct
{
ElemType *elem; //儲存空間基址
int length; //當前資料元素個數
int listsize; //當前分配的最大資料元素容量
}SqList;
三、13個基本操作
分別是:
建立線性表,清空線性表,銷燬線性表
判空線性表,判滿線性表,獲得當前資料元素個數
獲得指定位置的資料元素,定位符合一定條件的資料元素
獲得一個數據元素的前驅,獲得一個元素的後繼
插入資料元素,刪除資料元素
遍歷線性表
1、建立線性表
初始條件:一個未初始化的線性表結構體
Status InitList(SqList &L)
{
L.elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
//申請儲存空間
if(!L.elem)
exit(0);
L.length=0;//空表的長度為0
L.list=LIST_INT_SIZE;//初始資料元素儲存容量
return OK;
}
2、清空線性表
初始條件:線性表存在
操作結果:清空線性表(將當前元素個數賦值0,遍歷不出任何一個元素,相當於清空線性表)
Status ClearList(SqList &L)
{
L.length =0;
return Ok;
}
3、銷燬線性表
初始條件:線性表已存在
操作結果:銷燬線性表
Status Destroy(SqList &L)
{
free(L.elem);
L.elem=NULL;
L.length=0;
L.listsize=0;
return OK;
}
4、判空線性表
初始條件:線性表存在
操作結果:線性表為空返回true,不為空返回false
bool ListEmpty(SqList L)//不需要對線性表的成員變數進行改變,所以不使用引用
{
return (L.length==0)?true :false;
}
5、判滿線性表
初始條件:線性表存在
操作結果:若線性表已滿返回true,否則返回false
bool ListFull(SqList L)
{
return (L.length==L.listsize)?true:false;
}
6、獲取線性表當前元素個數
初始條件:線性表已存在
操作結果:返回線性表當前元素個數
int ListLength(SqList L)
{
return L.length;
}
7、獲得指定位置的資料元素
初始條件:線性表存在
操作結果:獲得指定位置的資料元素並賦值給e
Status GetElem(SqList L,int i, ElemType &e)
{
if(i<1||i>L.length)
exit(error);
e=*(L.elem+i-1);//(基址+i-1)即為第i個元素的地址
return OK;
}
8、定位元素(獲得符合一定條件的資料元素的位序)
初始條件:線性表已存在
操作結果:返回L中第一個與e滿足關係的元素的位序,若不存在返回0
(注意:compare()表示一個關係判定函式,滿足返回值為1,否則返回值為2,使用函式指標,方便呼叫)
int LocateElem(SqList L,ElemType e,status(*compare)(ElemType,ElemType))
{
Elem *p=L.elem; //P的初值為第一個元素的儲存位置
int i=1;//i的初值為第一個元素的位序
while(i<=L.length&&!compare(*p++,e))//越界或已找到滿足條件的元素
//i的最大可能值為L.length+1
{
if(i<=L.length)
return i;
else
return 0;
}
9、返回前驅
初始條件:線性表已存在,資料元素存在前驅
操作結果:查詢資料元素,若線性表中有該元素且前驅存在,將前驅拷貝給一個與資料元素資料型別相同的變數;若前驅不存在,上述變數無定義
//返回前驅,equal要提前宣告
Status PriorElem(SqList L,ElemType cur_e,ElemType &pre_e)
{
int a;
a=LocateElem(L,cur_e,equal);
if(!a||a==1)
{
cout<<"查詢失敗"<<endl;
return error;
}
pre_e=*(L.elem+a-2);
return OK;
}
10、返回後繼
初始條件:線性表已存在,資料元素存在後繼
操作結果:查詢資料元素,若線性表中有該元素且後繼存在,將後繼拷貝給一個與資料元素資料型別相同的變數;若後繼不存在,上述變數無定義
Status NextElem(SqList L,ElemType cur_e,ElemType &next_e)
{
int a;
a=LocateElem(L,cur_e,equal);
if(!a||a==L.length)
{
cout<<"查詢失敗"<<endl;
return error;
}
next_e=*(L.elem+a);
return OK;
}
11、插入一個數據元素
初始條件:線性表存在
操作結果:在L中第i個元素之前插入新的元素e,L的長度加1
Status ListInsert(SqList &L,int i,ElemType e)
{
ElemType *newbase,*q,*p;
if(i<1||i>L.length+1)//i值不合法
return error;
if(L.length>=L.listsize) //當前儲存空間已滿,增加分配
{
if(!(newbase=(ElemType*)realloc(L.elem,(L.listsize+LISTINCREMENT)*sizeof(ElemType))))
exit(0);//分配儲存空間失敗
L.elem=newbase;//新基址
L.listsize+=LISTINREMENT;//增加儲存容量
}
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;
}
12、刪除元素
初始條件:線性表已存在
操作結構:刪除第i個數據元素並返回其值,L的長度減1
Status ListDelete(SqList &L,int i,ElemType &e)
{
ElemType *p,*q;
if(i<1||i>L.length)//i值不合法
return error;
p=L.elem+i-1;//p為被刪除元素的位置
e=*p;//被刪除元素的值賦給e
q=L.elem+L.length-1;//表尾元素的位置
for(++p;p<=q;++p)
*(p-1)=*p;
L.length--;
return OK;
}
13、遍歷線性表
初始條件:線性表已存在
操作結果:依次對L的每個元素使用函式f(),f()可以是輸出函式,一旦操作失敗,則操作失敗
Status ListTraverse(SqList L, void(*f)(ElemType&))
{
ElemType *p=L.elem;
int i;
for(i=1;i<=L.length;i++)
f(*p++);
cout<<endl;
return OK;
}