1. 程式人生 > >連結串列-遊標實現(C語言版)

連結串列-遊標實現(C語言版)

如果用C/C++寫連結串列的話,用指標會比較方便,但很多語言都沒有指標,那麼怎麼實現比較好呢?遊標是個不錯的選擇。

在用指標實現的連結串列中,有這樣兩個特點:
1.資料存在一組結構體中,並且每個結構體都有指向下一個結構體的指標。
2.一個新的結構體可以通過malloc獲取記憶體,也可以用free來釋放記憶體。

遊標法也得滿足這兩個條件。滿足條件1比較簡單,用一個全域性的結構體陣列就行了;滿足條件2的話可以保留一個表,如圖:
0表示表頭,然後他們的初始關係是這樣這樣:

當執行malloc功能時,我們把表頭指向的單元拿出來使用,然後把表頭指向下一個空單元,執行free功能時,將目標單元回收就行了。
這個表取名叫CursorSpace,下面給出CursorSpace的malloc和free的程式碼:

static Position CursorAlloc(void)
{
    Position P;

    P = CursorSpace[0].Next;
    CursorSpace[0].Next = CursorSpace[P].Next;

    return P;
}

static void CursorFree(Position P)
{
    CursorSpace[ P ].Next = CursorSpace[ 0 ].Next;
    CursorSpace[ 0 ].Next = P;
}

將程式碼和圖結合起來試一試,應該很容易就能理解了。

下面給出完整程式碼:
1.標頭檔案:

#ifndef CURSORLIST_H_INCLUDED
#define CURSORLIST_H_INCLUDED

typedef double ElementType;
typedef int PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;

void InitializeCursorSpace( void );

List MakeEmpty(List L);
int IsEmpty(const List L);
int IsLast(const Position P,const List L);
Position
Find(ElementType X,const List L); void Delete(ElementType X,List L); Position FindPrevious(ElementType X,const List L); void Insert(ElementType X,List L,Position P); void DeleteList(List L); Position Header(const List L); Position First(const List L); Position Advance(const Position P); ElementType Retrieve(const Position P); #endif // CURSORLIST_H_INCLUDED

2。實現:

#include "CursorList.h"
#include <stdio.h>
#define SpaceSize 100

struct Node
{
    ElementType Element;
    Position Next;
};

struct Node CursorSpace[ SpaceSize ];

static Position CursorAlloc(void)
{
    Position P;

    P = CursorSpace[0].Next;
    CursorSpace[0].Next = CursorSpace[P].Next;

    return P;
}

static void CursorFree(Position P)
{
    CursorSpace[ P ].Next = CursorSpace[ 0 ].Next;
    CursorSpace[ 0 ].Next = P;
}

/* Return true if L is empty */
int IsEmpty(List L)
{
    return CursorSpace[L].Next == 0;
}

/* Return true if P is the last position in list L */
/* Parameter L is unused in this implementation */
int IsLast(Position P,List L)
{
    return CursorSpace[P].Next == 0;
}

/* Return Position of X in L;0 if not found */
/* Uses a header node */
Position Find(ElementType X,List L)
{
    Position P;

    P = CursorSpace[ L ].Next;
    while(P && CursorSpace[P].Element != X)
        P = CursorSpace[P].Next;

    return P;
}

/* Delete first occurrence of X in L; 0 if not found */
/* Assume use of a header node */
void Delete(ElementType X,List L)
{
    Position P,TmpCell;

    P = FindPrevious(X,L);

    if(!IsLast(P,L))
    {
        TmpCell = CursorSpace[ P ].Next;
        CursorSpace[ P ].Next = CursorSpace[ TmpCell ].Next;
        CursorFree(TmpCell);
    }
}

/* Insert (after legal position P) */
/* Header implementation assumed */
/* Parameter L is unused in this implementation */
void Insert(ElementType X,List L,Position P)
{
    Position TmpCell;

    TmpCell = CursorAlloc();
    if(TmpCell == 0)
        FatalError("Out of space!!!");

    CursorSpace[TmpCell].Element = X;
    CursorSpace[TmpCell].Next = CursorSpace[ P ].Next;
    CursorSpace[P].Next = TmpCell;
}

/* initialize the CursorSpace */
void InitCursorSpace()
{
    int i;
    for(i = 0; i < SpaceSize; i++)
        CursorSpace[i].Next = i==SpaceSize-1?0:i+1;
}

/* Find the front of the first X of The list */
/* Return 0 if not found */
Position FindPrevious(ElementType X,const List L)
{
    Position P;
    P = L;
    while(P&&CursorSpace[CursorSpace[P].Next].Element != X)
        P = CursorSpace[P].Next;
    return P;
}

/* Do something when the fatal error occurred */
void FatalError(char * s)
{
    printf("%s\n",s);
    /* stop the program if necessary */
}

int main()
{
    InitCursorSpace();
    List a = CursorAlloc();
    CursorSpace[a].Next = 0;
    Insert(1,a,a);
    Insert(0,a,a);
    Insert(12.998,a,a);
    Delete(12.998,a);
    //Delete(0,a);
    Position P = CursorSpace[a].Next;
    printf("%lf\n",CursorSpace[P].Element);
}

同樣在最後加了個main函式來測試一下。
如果有錯誤,請積極指正。

注:程式碼改編自《資料結構與演算法分析》第二版