1. 程式人生 > >資料結構 C語言 線性表 順序表 實現

資料結構 C語言 線性表 順序表 實現

#include<stdio.h>
#include<stdlib.h >

/*
C提供三種預處理。巨集定義、檔案包含、條件編譯 。
巨集 定 義:又稱為巨集代換、巨集替換,簡稱“巨集”。巨集定義格式:#define 識別符號 字串
檔案包含:#include<***.h>或者 #include“***.h(.c)”
條件編譯:(#ifndef 和  #endif 成對出現)作用:避免兩個欄位中間的預處理重複處理。
*/

#ifndef STATUS_H
#define STATUS_H

#define    TRUE        1            //真
#define    FALSE        0            //假
#define YES            1            //是
#define NO          0            //否
#define    OK            1            //通過
#define    ERROR        0            //錯誤
#define SUCCESS        1            //成功
#define UNSUCCESS    0            //失敗
#define    INFEASIBLE    -1            //不可行

#ifndef _MATH_H_                 //系統中已有此狀態碼定義,要避免衝突
#define    OVERFLOW    -2            //堆疊上溢
#define UNDERFLOW    -3            //堆疊下溢
#endif

/* 狀態碼識別型別 */
typedef int Status;

/* 巨集函式(使用define進行多行定義時要加\)*/
//函式暫停一段時間
#define Wait(x)\
 {\
    double _Loop_Num_;\
    for(_Loop_Num_=0.01; _Loop_Num_<=100000.0*x; _Loop_Num_+=0.01);\
 }//設立一個空迴圈

//摁Enter鍵繼續
#define PressEnter\
 {\
    fflush(stdin);\
    printf("Press Enter...");\
    getchar();\
    fflush(stdin);\
 }//fflush清空標準輸入流stdin

/*
getchar()函式等待輸入,直到按回車才結束。回車前的所有輸入字元都會逐個顯示在螢幕
但只有第一個字元作為函式的返回值。利用getchar函式讓程式除錯執行結束後
等待程式設計者按下鍵盤才返回編輯介面。
*/

#endif

#define LIST_INIT_SIZE 100     //定義線性順序表的容量置為100
#define LISTINCREMENT  10      //定義線性順序表的遞增量置為10
typedef int LElemType_Sq;      //定義線性順序表型別的別名
typedef struct SqList          //定義線性順序表的結構體並起名為SqList
{
    LElemType_Sq *elem;        //表的首地址
    int length;                //表的當前長度
    int listsize;              //表的容量
} SqList;

//順序表相關操作列表------------------------------------------------------------
Status InitList_Sq(SqList *L)
{
    //建立一個線性順序表-------------------------------------------------------1
    (*L).elem = (LElemType_Sq*)malloc(LIST_INIT_SIZE*sizeof(LElemType_Sq));
    if(!(*L).elem)    exit(OVERFLOW);
    (*L).length = 0;
    (*L).listsize = LIST_INIT_SIZE;
    return OK;
}

void ClearList_Sq(SqList *L)
{
    //清除線性順序表內容-------------------------------------------------------2
    (*L).length = 0;
}

void DestroyList_Sq(SqList *L)
{
    //銷燬線性順序表-----------------------------------------------------------3
    free((*L).elem);
    (*L).elem = NULL;
    (*L).length = 0;
    (*L).listsize = 0;
}

Status ListEmpty_Sq(SqList L)
{
    //判斷線性順序表是否為空---------------------------------------------------4
    return     L.length==0 ? TRUE : FALSE;
}

int ListLength_Sq(SqList L)
{
    //返回該線性順序表的長度---------------------------------------------------5
    return L.length;
}

Status GetElem_Sq(SqList L, int i, LElemType_Sq *e)
{
    //取得該線性順序表確定位置的內容並賦予e------------------------------------6
    if(i<1 || i>L.length)
        return ERROR;
    else
        *e = L.elem[i-1];
    return OK;
}

int LocateElem_Sq(SqList L, LElemType_Sq e, Status(*Compare)(LElemType_Sq, LElemType_Sq))
{
    //線上性順序表中找到與e等值的位置,並返回----------------------------------7
    int i = 1;
    while(i<=L.length && !Compare(e, L.elem[i-1]))
        ++i;
    if(i<=L.length)
        return i;
    else
        return 0;
}

Status PriorElem_Sq(SqList L, LElemType_Sq cur_e, LElemType_Sq *pre_e)
{
    //若cur_e不是線性順序表的第一個並且在表中存在與之相同的內容----------------8
    int i = 1;
    if(L.elem[0]!=cur_e)
    {
        while(i<L.length && L.elem[i]!=cur_e)
            ++i;
        if(i<L.length)
        {
            *pre_e = L.elem[i-1];
            return OK;
        }
    }
    return ERROR;
}

Status NextElem_Sq(SqList L, LElemType_Sq cur_e, LElemType_Sq *next_e)
{
    //若cur_e不是線性順序表的最後一個並且在表中存在與之相同的內容--------------9
    int i = 0;
    while(i<L.length && L.elem[i]!=cur_e)
        ++i;
    if(i<L.length-1)
    {
        *next_e = L.elem[i+1];
        return OK;
    }
    return ERROR;
}

Status ListInsert_Sq(SqList *L, int i, LElemType_Sq e)
{
    //線上性順序表位序i的前面插入e元素----------------------------------------10
    LElemType_Sq *newbase;
    LElemType_Sq *p, *q;
    if(i<1 || i>(*L).length+1)
        return ERROR;
    if((*L).length >= (*L).listsize)
    {
        newbase = (LElemType_Sq*)realloc((*L).elem, ((*L).listsize+LISTINCREMENT)*sizeof(LElemType_Sq));
        if(!newbase)  exit(OVERFLOW);
        (*L).elem = newbase;
        (*L).listsize += LISTINCREMENT;
    }
    q = &(*L).elem[i-1];
    for(p=&(*L).elem[(*L).length-1]; p>=q; --p)
        *(p+1) = *p;
    *q = e;
    (*L).length++;
    return OK;
}

Status ListDelete_Sq(SqList *L, int i, LElemType_Sq *e)
{
    //刪除線性順序表位序為i的元素,並將之返回---------------------------------11
    LElemType_Sq *p, *q;
    if(i<1||i>(*L).length)return ERROR;
    p = &(*L).elem[i-1];
    *e = *p;
    q = (*L).elem+(*L).length-1;
    for(++p; p<=q; ++p)
        *(p-1) = *p;
    (*L).length--;
    return OK;
}

Status ListTraverse_Sq(SqList L, void(*Visit)(LElemType_Sq))
{
    //遍歷輸出整個線性順序表--------------------------------------------------12
    int i;
    for(i=0; i<L.length; i++)
        Visit(L.elem[i]);
    return OK;
}

//函式指標----------------------------------------------------------------------
Status Compare(LElemType_Sq e, LElemType_Sq data)   //Compare指標函式的實現
{
    return data==e ? TRUE : FALSE;
}

void PrintElem(LElemType_Sq e)                      //visit指標函式的實現
{
    printf("%d ", e);
}

//求並集相關函式----------------------------------------------------------------
Union(SqList *La, SqList Lb)
{
    //合併兩個非遞減線性表成新的非遞減排列線性(A=A∪B)------------------------13
    int La_len, Lb_len;
    int i;
    LElemType_Sq e;
    La_len = ListLength_Sq(*La);
    Lb_len = ListLength_Sq(Lb);
    for(i=1; i<=Lb_len; i++)
    {
        GetElem_Sq(Lb, i, &e);
        if(!LocateElem_Sq(*La, e, Compare))
            ListInsert_Sq(La, ++La_len, e);
    }
}

Status equal(SqList e1, SqList e2)
{
    //判斷兩個函式相等否------------------------------------------------------14
    if (e1.length != e2.length)
        return FALSE;
    else
    {
        int i;
        for (i=0 ; i<e1.length; i++)
        {
            if(e1.elem[i] != e2.elem[i])
            {
                return FALSE;
            }
        }
        if (i >= e1.length)
        {
            return TRUE;
        }
    }
}

//順序表歸併相關操作------------------------------------------------------------
void MergeSqList_1(SqList La, SqList Lb, SqList *Lc)
{
    //呼叫順序表函式進行合併--------------------------------------------------15
    int La_len, Lb_len;
    int i, j, k;
    LElemType_Sq ai, bj;
    i = j = 1;
    k = 0;
    InitList_Sq(Lc);
    La_len = ListLength_Sq(La);
    Lb_len = ListLength_Sq(Lb);
    while(i<=La_len && j<=Lb_len)
    {
        GetElem_Sq(La, i, &ai);
        GetElem_Sq(Lb, j, &bj);
        if(ai<=bj)
        {
            ListInsert_Sq(Lc, ++k, ai);
            i++;
        }
        else
        {
            ListInsert_Sq(Lc, ++k, bj);
            j++;
        }
    }
    while(i<=La_len)
    {
        GetElem_Sq(La, i++, &ai);
        ListInsert_Sq(Lc, ++k, ai);
    }
    while(j<=Lb_len)
    {
        GetElem_Sq(Lb, j++, &bj);
        ListInsert_Sq(Lc, ++k, bj);
    }
}

void MergeSqList_2(SqList La, SqList Lb, SqList *Lc)
{
    //呼叫順序表函式進行合併--------------------------------------------------16
    LElemType_Sq *pa, *pb, *pc;
    LElemType_Sq *pa_last, *pb_last;
    pa = La.elem;
    pb = Lb.elem;
    (*Lc).listsize = (*Lc).length = La.length + Lb.length;
    pc = (*Lc).elem = (LElemType_Sq *)malloc((*Lc).listsize*sizeof(LElemType_Sq));
    if(!pc)     exit(OVERFLOW);
    pa_last = La.elem + La.length - 1;
    pb_last = Lb.elem + 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++;
}

//主函式------------------------------------------------------------------------
int main()
{
    SqList L;
    int i;
    LElemType_Sq e;

    printf("▼1\n▲函式 InitList_Sq 測試...\n");        //1.函式InitList_Sq測試
    {
        printf("初始化順序表 L ...\n");
        InitList_Sq(&L);
        printf("\n");
    }
    PressEnter;

    printf("▼4\n▲函式 ListEmpty_Sq 測試...\n");        //4.函式ListEmpty_Sq測試
    {
        ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n");
        printf("\n");
    }
    PressEnter;

    printf("▼10\n▲函式 ListInsert_Sq 測試...\n");        //10.函式ListInsert_Sq測試
    {
        for(i=1; i<=6; i++)
        {
            printf("作為示範,在 L 第 %d 個位置插入 \"%d\"...\n", i, 2*i);
            ListInsert_Sq(&L, i, 2*i);
        }
        printf("\n");
    }
    PressEnter;

    printf("▼12\n▲函式 ListTraverse_Sq 測試...\n");    //12.函式ListTraverse_Sq測試
    {
        printf(" L 中的元素為:L = ");
        ListTraverse_Sq(L, PrintElem);
        printf("\n\n");
    }
    PressEnter;

    printf("▼5\n▲函式 ListLength_Sq 測試...\n");        //5.函式ListLength_Sq測試
    {
        i = ListLength_Sq(L);
        printf(" L 的長度為 %d \n", i);
        printf("\n");
    }
    PressEnter;

    printf("▼11\n▲函式 ListDelete_Sq 測試...\n");        //11.函式ListDelete_Sq測試
    {
        ListDelete_Sq(&L, 6, &e);
        printf("刪除 L 中第 6 個元素 \"%d\" ...\n", e);
        printf(" L 中的元素為:L = ");
        ListTraverse_Sq(L, PrintElem);
        printf("\n\n");
    }
    PressEnter;

    printf("▼6\n▲函式 GetElem_Sq 測試...\n");            //6.函式GetElem_Sq測試
    {
        GetElem_Sq(L, 4, &e);
        printf(" L 中第 4 個位置的元素為 \"%d\" \n", e);
        printf("\n");
    }
    PressEnter;

    printf("▼7\n▲函式 LocateElem_Sq 測試...\n");          //7.函式LocateElem_Sq測試
    {
        i = LocateElem_Sq(L, 7, Compare);
        printf(" L 中第一個元素值大於 \"7\" 的元素的位置為 %d \n", i);
        printf("\n");
    }
    PressEnter;

    printf("▼8\n▲函式 PriorElem_Sq 測試...\n");        //8.函式PriorElem_Sq測試
    {
        PriorElem_Sq(L, 6, &e);
        printf("元素 \"6\" 的前驅為 \"%d\" \n", e);
        printf("\n");
    }
    PressEnter;

    printf("▼9\n▲函式 NextElem_Sq 測試...\n");        //9.函式NextElem_Sq測試
    {
        NextElem_Sq(L, 6, &e);
        printf("元素 \"6\" 的後繼為 \"%d\" \n", e);
        printf("\n");
    }
    PressEnter;

    printf("▼2\n▲函式 ClearList_Sq 測試...\n");        //2.函式ClearList_Sq測試
    {
        printf("清空 L 前:");
        ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n");
        ClearList_Sq(&L);
        printf("清空 L 後:");
        ListEmpty_Sq(L) ? printf(" L 為空!!\n") : printf(" L 不為空!\n");
        printf("\n");
    }
    PressEnter;

    printf("▼3\n▲函式 DestroyList_Sq 測試...\n");        //3.函式DestroyList_Sq測試
    {
        printf("銷燬 L 前:");
        L.elem ? printf(" L 存在!\n") : printf(" L 不存在!!\n");
        DestroyList_Sq(&L);
        printf("銷燬 L 後:");
        L.elem ? printf(" L 存在!\n") : printf(" L 不存在!!\n");
        printf("\n");
    }
    PressEnter;

    printf("▼13\n▲函式 Union 測試...\n");
    SqList La, Lb;
    LElemType_Sq a[] = {3, 5, 8, 11, 12};
    LElemType_Sq b[] = {2, 4, 6, 7, 9, 10, 13};
    InitList_Sq(&La);                   //建立線性順序表La
    InitList_Sq(&Lb);                   //建立線性順序表Lb
    for(i=1; i<=5; i++)
        ListInsert_Sq(&La, i, a[i-1]);  //初始化La
    for(i=1; i<=7; i++)
        ListInsert_Sq(&Lb, i, b[i-1]);  //初始化Lb
    printf("La = ");                    //輸出La
    ListTraverse_Sq(La, PrintElem);
    printf("\n");
    printf("Lb = ");                    //輸出Lb
    ListTraverse_Sq(Lb, PrintElem);
    printf("\n\n");
    printf("La = La∪Lb = ");            //輸出新表La的內容
    Union(&La,Lb);
    ListTraverse_Sq(La, PrintElem);
    printf("\n\n");
    PressEnter;

    printf("▼14\n▲函式 equal 測試...\n");
    equal(La,Lb)?printf("表La和Lb相等\n"):printf("表La和Lb不相等\n");
    equal(La,La)?printf("表La和La相等\n"):printf("表La和La不相等\n");
    PressEnter;

    printf("▼15\n▲函式 MergeSqList_1 測試...\n");
    SqList Lc1;
    InitList_Sq(&La);
    InitList_Sq(&La);                    //初始化La
    for(i=1; i<=5; i++)
        ListInsert_Sq(&La, i, a[i-1]);
    InitList_Sq(&Lb);                    //初始化Lb
    for(i=1; i<=7; i++)
        ListInsert_Sq(&Lb, i, b[i-1]);
    MergeSqList_1(La, Lb, &Lc1);        //合併A與B,演算法2.6
    printf("合併La和Lb為Lc1 = ");         //輸出Lc1
    ListTraverse_Sq(Lc1, PrintElem);
    printf("\n\n");
    PressEnter;

    printf("▼16\n▲函式 MergeSqList_2 測試...\n");
    SqList Lc2;
    InitList_Sq(&La);
    InitList_Sq(&La);                    //初始化La
    for(i=1; i<=5; i++)
        ListInsert_Sq(&La, i, a[i-1]);
    InitList_Sq(&Lb);                    //初始化Lb
    for(i=1; i<=7; i++)
        ListInsert_Sq(&Lb, i, b[i-1]);
    MergeSqList_2(La, Lb, &Lc2);        //合併A與B,演算法2.6
    printf("合併La和Lb為Lc2 = ");         //輸出Lc1
    ListTraverse_Sq(Lc2, PrintElem);
    printf("\n\n");
    PressEnter;

    return 0;
}