數據結構之表(C語言實現)

數據結構之表(C語言實現)

抽象數據類型 (abstract data type,ADT)

抽象數據類型是一些操做的集合。抽象數據類型是數學中的定義,在ADT中,咱們不關心操做是如何被實現的。所以,這能夠看作是模塊化的擴充。
例如表,樹,圖和它們的操做一塊兒能夠看作是抽象數據類型,就想整數,實數和布爾變量是數據類型同樣。整數,實數和布爾變量有它們的操做,抽象數據類型也有它們本身的操做。數組

表 ADT

咱們將形如A1,A2,A3,...,An的一列數稱爲表。
表的大小:表中的元素的個數稱爲表的大小,大小爲0的表稱爲空表。
對於除空表外,咱們稱Ai+1是Ai的後繼,Ai-1是Ai的前驅,其中表的第一個元素A1不定義前驅,最後一個元素An不定義後繼。數據結構

表的數組實現

對於表的全部操做均可以經過數組來實現,數組使得PrintList和Find以線性的時間執行,而FindIndex則花費常數的執行時間。然而,插入和刪除的代價是昂貴的,例如在第一個元素位置插入,須要將後面的全部元素日後移一個位置出來,同理刪除也是如此。所以這兩種操做的最壞狀況是O(N)。平均來看,這兩種運算都要移動表的一半的元素,仍然須要線性時間。
由於插入和刪除的運行時間是如此的慢,並且表的大小還須要事先知道,因此簡單數組通常不用來實現表的結構。模塊化

鏈表

爲了不插入和刪除的線性開銷,咱們須要運行表能夠不連續存儲,不然表的部分或所有須要總體移動,而如圖表達了鏈表的通常想法。
在鏈表中,每一個結構均包含有表元素和指向包含包含該元素後繼元素的結構的指針,咱們稱之爲next指針,最後一個元素的next指針指向null,ANSI C規定NULL爲0。函數

程序設計細節
爲了更方便的實現鏈表中的操做,咱們一般會增長一個頭結點,並將它指向第一個元素。

源碼設計

//鏈表的結構
struct Node;
typedef struct Node *ptrToNode ;
typedef ptrToNode List ;
typedef ptrToNode Position;

struct Node{
    ElementType Element;
    Position Next;
};

//判斷表是否爲空
int IsEmpty(List L){
    return L->Next == NULL;
}

//判斷當前是否爲鏈表的末尾
int IsLast(Position P,List L){
    return P->Next == Null;
}

//查找函數
Position Find(Element X,List L){
    Position P;
    P = L->Next;
    while(P != NULL && P->Element != X){
        P = P->Next;
    }
    return P;
}

//刪除元素
void Delet(ElementType X,List L){
    Position P, TempNode;
     P = FindPrevious(X, L);
     if(!IsLast(P,L)){
         TempNode = P->Next;
         P->Next = TempNode->Next;
         free(TmpNode);
     }
}

//查找某元素的前一個元素
Position FindPrevious(ElementType X,List L){
    Position P;
    P = L;
    while(P->Next != NULL && P->Next->Element != X){
        P = P->Next;
    }
    return P;
}

//插入元素
void Insert(ElementType X,List L,Position P){
    Position TempNode ;
    TempNode = malloc(sizeof(struct Node));
    if(TempNode == NULL){
        printf("malloc error");
        return ;
    }
    TempNode->Element = x;
    TempNode->Next = P->Next;
    p->Next = TempNode;
}

//刪除鏈表
void DeleteList(List L){
    Position P,Tmp;
    p = L->Next;
    L->Next = NULL;\
    while(p != NULL){
        Tmp = P->Next;
        free(p);
        p = Tmp;
    }
}
雙鏈表

當涉及到倒序掃描鏈表時,雙鏈表就很是方便了。雙鏈表和單鏈表的區別就是:雙鏈表中存在兩個指針域,一個指向當前元素的前驅,另外一個指向當前元素的後繼。有了雙向鏈表,能夠不用在訪問當前元素的前一個元素了,不過,雙鏈表方便的同時,增長了空間的開銷。指針

循環鏈表

讓最後的單元指向第一個單元構成循環,這樣的鏈表被稱爲循環鏈表。它既能夠有表頭,也能夠沒有表頭(如有表頭,則最後一個元素指針指向表頭)。code

案例實戰

一元多項式
咱們能夠用表來定義模擬一元多項式的抽象數據類型。對於大多數係數非零的多項式,咱們能夠採用一個簡單的數組來進行存儲,數組的下標表示多項式的次冪,下標的值表示多項式的係數。可是對於係數相差較大,大部分的係數爲0的多項式,採用數組將會浪費極大的空間。下面咱們就採用數組的方法來定義多項式的抽象數據類型。源碼

typddef struct{
    int CoeffArray[ MaxDegree + 1 ];
    int HighPower;
}* Polynomial;

//多項式初始化爲0
void ZeroPolynomial(Polynomial Poly){
    int i;
    for( i=0; i <= MakDegree; i++){
        Poly->CoeffArray[i] = 0;
    }
    Poly->HighPower = 0;
}

//兩個多項式相加
void AddPolynomial(const Polynomial poly1, const Polynomial poly2, Polynomial polysum){
    int i;
    ZeroPolynomial(polysum);
    polysum->HighPower = Max(poly1->HighPower,poly2->HighPower);
    for( i = polysum->HighPower; i>=0; i--){
        polysum->CoeffArray[i] = poly1->CoeffArray[i] + poly2->CoeffArray[i];
    }
}

//兩個多項式的乘法
void MultPolynomial(const Polynomial poly1, const Polynomial poly2, Polynomial polymult){
    int i,j;
    ZeroPolynomial(polymult);
    polymult->HighPower = poly1->HighPower + poly2->HighPower;
    if(polymult->HighPower > MaxDegree){
        printf("MaxDegree ERROR");
    }else{
        for( i=0; i <= poly1->HighPower; i++ ){
            for( j=0; poly2->HighPower; j++){
                polysum->CoeffArray[i+j] = poly1->CoeffArray[i] * poly2->CoeffArray[i];
            }
        }
    }
}
相關文章
相關標籤/搜索