第一部分 線性表的順序存儲(二)--動態分配

(二)線性表的動態分配順序存儲
    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++;
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章