1. 程式人生 > 實用技巧 >資料結構-線性表

資料結構-線性表

線性表

定義

具有相同特性的資料元素的一個有限序列。

由n(n≥0)個數據元素(結點)a1,a2,...an組成的有限序列。

  • 資料元素的個數n定義為表的長度
  • 當n=0時為空表
  • 當n>0時記為(a1,a2,...an)

同一線性表中的元素必定具有相同特性,資料元素間的關係是線性關係。

邏輯結構儲存結構一致。

邏輯特徵

  • 開始結點

    \[在非空的線性表,有且僅有一個開始結點a_1,沒有直接前趨,而僅有一個直接後續a_2 \]

  • 終端結點

    \[有且僅有一個終端結點a_n,沒有直接後續,而僅有一個直接前趨a_{n-1} \]

  • 內部結點

\[內部結點a_i(2 \leq i \leq n-1)都有且僅有一個直接前趨a_{i-1}和一個直接後繼a_{i-1} \]

線性表是一種典型的線性結構

抽象資料型別線性表定義

ADT List{
	資料物件:D = {ai|ai屬於Elemset,(i=1,2,...,n,n≥0)}
	資料關係:R = {<ai-1,ai>|ai-1,ai屬於D,(i=2,3,...,n)}
	基本操作:
		InitList(&L);
		...
}ADT List

基本操作

  • InitList(&L)

    操作結果:構造一個空的線性表L。

  • DestroyList(&L)

    初始條件:線性表L已經存在。

    操作結果:銷燬線性表L。

  • ClearList(&L)

    初始條件:線性標L已經存在。

    操作結果:將線性表L重置為空表。

  • ListEmpty(L)

    初始條件:線性表L已經存在。

    操作結果:若線性表L為空表,則返回TRUE,反之返回FALSE。

  • ListLength(L)

    初始條件:線性表L已經存在。

    操作結果:返回線性表L中的資料元素個數。

  • GetElem(L,i,&e)

    初始條件:線性表L已經存在,1≤i≤ListLength(L)。

    操作結果:用e返回線性表L中第i個數據元素的值。

  • LocateElem(L,e,compare())

    初始條件:線性表L已經存在,compare()是資料元素判定函式。

    操作結果:返回L中第1個與e滿足compare()的資料元素的位序。若不存在則返回值為0。

  • PriorElem(L,cur_e,&pre_e)

    初始條件:線性表L已經存在。

    操作結果:若cur_e是L的資料元素,且不是第一個,則用pre_e返回它的前驅,反之則失敗,返回NULL。

  • NextElem(L,cur_e,&next_e)

    初始條件:線性表L已經存在。

    操作結果:若cur_e是L的資料元素,且不是最後一個,則用next_e返回它的後繼,反之則失敗,返回NULL。

  • ListInsert(&L,i,e)

    初始條件:線性表L已經存在,1≤i≤ListLength(L)+1。

    操作結果:在L的第i個位置之前插入新的資料元素e,L的長度加一。

  • ListDelete(&L,i,&e)

    初始條件:線性表L已經存在,1≤i≤ListLength(L)。

    操作結果:刪除L的第i個數據元素,並用e返回其值,L的長度減一。

  • ListTraverse(&L,visited())

    初始條件:線性表L已經存在。

    操作結果:依次對線性表中每個元素呼叫visited()。

線性表順序儲存表示

隨機存取法

\[所有資料元素的儲存位置均可由第一個資料元素的儲存位置得到,儲存單元為l:\\LOC(a_i) = LOC(a_1) + (i-1)\times l \]

可以根據公式計算出任何一個數據元素的儲存地址,所以訪問每個元素所花時間相等。

模板

#define LIST_INIT_SIZE 100 //線性表儲存空間的初始分配量
typedef struct{
    ElemType elem[LIST_INIT_SIZE];
    int length;
}SqList;

例子

多項式

#define MAXSIZE 1000
typedef struct{		//多項式定義
    float p;		//係數
    int e;			//指數
}Polynomial;

typedef struct{
    Polynomial *elem;	//儲存空間的基地址
    int length;			//多項式中當前項的個數
}SqList;

void main(){
    Polynomial a[MAXSIZE];
    int i;
    for(i=0;i<MAXSIZE;i++){
        Polynomial temp;
        char msg;
        printf("輸入係數:");
        scanf("%f",&temp.p);
        printf("輸入指數:");
        scanf("%d",&temp.e);
        a[i] = temp;
        printf("是否退出(y):\n");
        msg = getch();
        if(msg == 'y'){
            break;
        }
    }
    SqList b;
    b.elem = a;
    b.length = i+1;
    for(i=0;i<b.length;i++){
        Polynomial temp;
        temp = b.elem[i];
        if(temp.e == 0){
            printf("%0.2f +",temp.p);
        }else if(temp.e == 1){
            printf("%0.2fx +",temp.p);
        }else{
        	printf("%0.2fx^%d +",temp.p,temp.e);
        }
    }
}

查詢

平均查詢長度ASL(Average Search Length)

為確定記錄在表中的位置,需要與給定值進行比較的關鍵字的個數的期望值叫做查詢演算法的平均查詢長度

\[對含有n個記錄的表,查詢成功時:\\ASL = \sum_{i=1}^n{P_iC_i}\\其中P_i為第i個記錄被查詢的概率,C_i為找到第i個記錄需要比較的次數。 \]

順序查詢的平均查詢長度:

\[ASL=P_1+2P_2+...+(n-1)P_{n-1}+nP_n\\ 假設,每個記錄的查詢概率相等:P_i=\frac{1}{n}\\ 則:ASL_{ss}=\frac{1}{n}(1+2+...+n)\\ 根據等差數列求和公式:\frac{(a_1+a_n)n}{2}得 \\ ASL_{ss}=\frac{1}{n}\frac{n(n+1)}{2}\\ =\frac{n+1}{2}\\ ASL_{ss}= \sum_{i=1}^n{P_iC_i}=\frac{1}{n}\sum_{i=1}^n{i}=\frac{n+1}{2} \]

\[平均時間複雜度為O(n)\\ \frac{n+1}{2}=\frac{1}{2}+ \frac{n}{2}=\frac{1}{2}+\frac{1}{2}\times n=n\\ 平均空間複雜度為S(n) = O(1) \]

插入

插入位置在最後:不需要移動任何元素

插入位置在中間:移動元素的個數與插入的位置有關

插入位置在最前面:需要移動所有元素

平均移動次數

\[能夠移動的位數為n+1,每個位的概率為\frac{1}{n+1},需要移動的位數由指定位數i決定\\需要移動的次數為(n-i+1)\\ E_{ins} = \frac{1}{n+1}\sum_{i=1}^{n+1}(n-i+1)\\ =\frac{1}{n+1}((n-1+1)+...+(n-n+1)+(n-(n+1)+1))\\ =\frac{1}{n+1}\frac{n(n+1)}{2}\\ =\frac{n}{2} \]

\[平均時間複雜度為O(n)\\ \frac{n}{2}=\frac{1}{2}\times n=n\\ 平均空間複雜度為S(n) = O(1) \]

刪除

刪除位置在最後:不需要移動任何元素

刪除位置在中間:移動元素的個數與刪除的位置有關

刪除位置在最前面:需要移動所有元素

平均移動次數

\[能夠移動的位數為n,每個位的概率為\frac{1}{n},需要移動的位數由指定位數i決定\\ 需要移動的次數為(n-i)\\ E_{del}=\frac{1}{n}\sum_{i=1}^n(n-i)\\ =\frac{1}{n}((n-1)+(n-2)+...+n-(n-1)+n-n)\\ =\frac{1}{n}\frac{(n-1)n}{2}\\ =\frac{n-1}{2} \]

\[平均事件複雜度為O(n)\\ \frac{n-1}{2}=\frac{n}{2}-\frac{1}{2}=\frac{1}{2}\times n -\frac{1}{2} = n\\ 平均空間複雜度為S(n) = O(1) \]

優點

  • 儲存密度大(結點本身所佔儲存量/結點結構所佔儲存量=1)
  • 可以隨機存取表中任一元素

缺點

  • 在插入、刪除某一元素時,需要移動大量元素
  • 浪費儲存空間(定義陣列的時候)
  • 屬於靜態儲存形式,資料元素的個數不能自由擴充(固定的陣列大小,有上限)

線性表的鏈式儲存表示

  • 用一組物理位置任意的儲存單元來存放線性表的資料元素
  • 這組儲存單元可連續,也可不連續
  • 連結串列中元素的邏輯次序和物理次序不一定相同
  1. 結點:資料元素的儲存映像。由資料域指標域組成

  2. 連結串列:n個結點由指標鏈組成一個連結串列。

  3. 單鏈表、雙鏈表、迴圈連結串列、雙向迴圈連結串列。

    • 單鏈表:結點只有一個指標域的連結串列,每個結點指向下一個結點,最後一個結點指向空。
    • 雙鏈表:結點由兩個指標域的連結串列,每個結點分別指向前一個結點和下一個結點,最後一個結點的指向前一個結點和空。
    • 迴圈鏈:首尾相接的連結串列,最後一個結點指向頭結點。
    • 雙向迴圈連結串列:首尾相接的雙鏈表
  4. 頭指標、頭結點和首元結點

    • 頭指標:指向連結串列中第一個結點的指標;
    • 頭結點:資料域中不儲存資料,指標域指向首元結點;(可無)
      • 無頭結點:不利於儲存,連結串列的基本資訊
      • 有頭結點:可用來儲存連結串列的基本資訊,如:表長等
    • 首元結點:連結串列中第一個儲存資料的結點。

順序存取

訪問每個資料元素的時間與所處位置有關。

模板

typedef struct Lnode{
    ElemType data;			//資料域
    struct Lnode *next;		//指標域
}Lnode,*LinkList;			//Lnode為這個結構體的型別,*LinkList為指向這個結構體的指標型別

例如

多項式

typedef struct{
    int zhishu;
    float xishu;
}ElemType;

typedef struct Lnode{
    ElemType data;
    struct Lnode *next;
}Lnode,*LinkList;

操作與實現

單鏈表

  • 單鏈表初始化
Lnode * InitList(){
    Lnode *L = (Lnode *) malloc(sizeof(Lnode));
    if (L == NULL){
        exit(0);
    }
    L->data = 10;
    L->next = NULL;
    return L;
}
  • 檢查連結串列是否為空
int IsEmpty(Lnode *L){
    if(L->next){
        return 1;
    }else{
        return 0;
    }
}
  • 銷燬單鏈表
void DestroyList(Lnode *L){
    Lnode *p;
    while(L){
        p = L;
        L = L->next;
        free(p);
        p->next = NULL;
    }
}
  • 清空單鏈表
void ClearList(Lnode *L){
    Lnode *p,*q;
    p = L->next;
    while(p){
        q = p->next;
        free(p);
        p = q;
    }
    L->next = NULL;
}
  • 計算連結串列表長
int ListLength(Lnode *L){
    Lnode *p;
    int length = 0;
    p = L->next;
    while (p){
        p = p->next;
        length++;
    }
    return length;
}
  • 取值
ElemType GetElem(Lnode *L,int index){
    Lnode *p = L->next;
    int temp = 1;
    while (p && temp < index){
        p = p->next;
        temp++;
    }
    if (p && temp == index){
        return p->data;
    }
}
  • 按值查詢
Lnode * LocateElem(Lnode *L,ElemType data){
    Lnode *p = L->next;
    while (p){
        if (p->data.xishu == data.xishu && p->data.zhishu == data.zhishu){
            break;
        }
        p = p->next;
    }
    return p;
}
  • 插入至指定位置
int ListInsert(Lnode *L,int index,ElemType data){
    Lnode *p = L;
    int temp = 0;
    while (p && temp<index-1){
        p = p->next;
        temp++;
    }
    if (p && temp == index){
        Lnode *s = (Lnode *)malloc(sizeof(Lnode));
        s->data = data;
        s->next = p->next;
        p->next = s;
        return 1;
    }
    return 0;
}
  • 刪除指定位置結點
int DeleteList(Lnode *L,int index){
    Lnode *p = L;
    int temp = 0;
    while (p && temp<index-1){
        p = p->next;
        temp++;
    }
    if (p && temp==index-1){
        Lnode *s = p->next;
        p->next = s->next;
        free(s);
    }
}
  • 頭插法
void ListInsert_Head(Lnode *L,ElemType data[]){
    //此程式碼用CLion測試過,其實sizeof(data)應該為(sizeof(data)/sizeof(ElemType))-1,不知道為什麼CLion自動計算長度了。
    for (int i = sizeof(data); i > -1 ; --i) {
        Lnode *s = (Lnode *)malloc(sizeof(Lnode));
        s->data = data[i];
        s->next = L->next;
        L->next = s;
    }
}
  • 尾插法
void ListInsert_Last(Lnode *L,ElemType data[]){
    Lnode *p = L;
    //此程式碼用CLion測試過,其實sizeof(data)應該為(sizeof(data)/sizeof(ElemType))-1,不知道為什麼CLion自動計算長度了。
    for (int i = 0; i <= sizeof(data) ; ++i) {
        Lnode *s = (Lnode *)malloc(sizeof(Lnode));
        s->data = data[i];
        s->next = NULL;
        p->next = s;
        p = s;
    }
}

時間效率分析

  1. 查詢

    線性連結串列只能順序存取,只能從頭指標開始找,查詢時間複雜度為O(n)。

  2. 插入和刪除

    插入和刪除只需要修改指標,所以時間複雜度為O(1),如需刪除指定位置的結點,就需要從頭查詢其指定位置的前驅結點,所以時間複雜度為O(n)。

迴圈連結串列

由於表的操作通常是在表的首尾進行操作,而連結串列的頭指標表示的查詢第一個的時間複雜度為O(1)、查詢最後一個的時間複雜度為O(n),因此引入尾指標,尾指標表示的查詢第一個的時間複雜度為O(1)、查詢最後一個的時間複雜度為O(1)。

尾指標

最後一個結點的指向頭結點。

  • 單鏈錶轉迴圈連結串列(尾指標)
Lnode * ChangeList(Lnode *L){
    Lnode *p = L;
    while (L){
        if (L->next == NULL){
            L->next = p;
            break;
        }
        L = L->next;
    }
    return L;
}
  • 迴圈連結串列新增(尾指標)
Lnode * AddCirculationList(Lnode *L,ElemType data){
    Lnode *p = L;
    Lnode *s = (Lnode *)malloc(sizeof(Lnode));
    s->data = data;
    s->next = L->next;
    L->next = s;
    return s;
}
  • 合併迴圈連結串列(尾指標)
Lnode * MergeList(Lnode *L,Lnode *P){
    Lnode *l = L->next;
    L->next = P->next->next;
    free(P->next);
    P->next = l;
    return P;
}

雙向連結串列

在單鏈表的每個結點中增加一個指向其直接前驅的指標域prior

  • 查詢
LnodeDul * GetElemDul(LnodeDul *L,int index){
    LnodeDul *p = L;
    int temp = 0;
    while (p && temp<index){
        p = p->next;
        temp++;
    }
    if (p && temp == index){
        return p;
    }
}
  • 插入
int ListInsertDul(Lnode *L,int index,ElemType data){
    LnodeDul *p;
    if (!(p = GetElemDul(L,index))){
        return 0;
    }
    LnodeDul *s = (LnodeDul *)malloc(sizeof(LnodeDul));
    s->data = data;
    s->prior = p->prior;
    p->prior->next = s;
    s->next = p;
    p->prior = s;
    return 1;
}
  • 刪除
int ListDeleteDul(LnodeDul *L,int index){
    LnodeDul *p;
    if (!(p=GetElemDul(L,index))){
        return 0;
    }
    p->prior->next = p->next;
    p->next->prior = p->prior;
    free(p);
    return 1;
}

單鏈表、迴圈連結串列、雙向連結串列、雙向迴圈連結串列時間效率比較

帶頭結點 找頭結點 找尾結點 找當前結點p的前驅結點
單鏈表(頭指標L) L->next 時間複雜度O(1) 從頭遍歷 時間複雜度O(n) 無法找到
迴圈連結串列(頭指標L) L->next 時間複雜度O(1) 從頭遍歷 時間複雜度O(n) 從P->next遍歷 時間複雜度O(n)
迴圈連結串列(尾指標R) R->next 時間複雜度O(1) R本身 時間複雜度O(1) 從P->next遍歷 時間複雜度O(n)
雙向迴圈連結串列(頭指標L) L->next 時間複雜度O(1) L->prior 時間複雜度O(1) p->prior 時間複雜度O(1)

優點

  • 不需要一段連續的記憶體空間;

  • 結點空間可以動態申請和釋放;

  • 插入和刪除時不需要移動資料元素,只需要改變結點的指標域即可。

缺點

  • 儲存密度小,每個結點的指標域需額外佔用儲存空間。
  • 查詢時間複雜度高,因為鏈式儲存結構是順序存取,所以查詢需要從頭找。

儲存密度

儲存密度越大,儲存空間利用率越高。順序表儲存密度為1,連結串列儲存密度小於1。

\[儲存密度=\frac{結點資料佔用空間}{結點總佔用空間} \]

順序表與連結串列的比較

線性表的合併

List union(List La,List Lb){
    //獲取長度
    La_len = ListLength(La);
    Lb_len = ListLength(Lb);
    //把Lb中每一個元素在La中查詢,沒找到,則新增;反之,則跳過。
    for(int i = 1;i<=Lb_len;i++){
        ElemType e = GetElem(Lb,i);
        if(!LocatElem(La,e)){
            ListInsert(La,++La_len,e);
        }
    }
}

時間複雜度為:O(ListLength(La)*ListLength(Lb))

空間複雜度為:O(1)

有序表的合併(順序表)

SqList MergeList(SqList La,SqList Lb){
    Polynomial *pa = La.elem;
    Polynomial *pb = Lb.elem;
    SqList pc;
    pc.length = La.length+Lb.length;
    pc.elem = Polynomial[pc.length];
    Polynomial pc[] = pc.elem;
    pa_end = La.elem+La.length-1;
    pb_end = Lb.elem+Lb.length-1;
    while(pa<=pa_end && pb<=pb_end){
        if(*pa <= *pb){
            *pc++ = *pa++;
        }else{
            *pc++ = *pb++;
        }
    }
    while(pa <= pa_end){
        *pc++ = *pa++;
    }
    while(pb <= pb_end){
        *pc++ = *pb++;
    }
    return pc;
}

時間複雜度為:O(La.length+Lb.length)

空間複雜度為:O(La.length+Lb.length)

有序表的合併(連結串列)

void ListUnion(Lnode *La,Lnode *Lb){
    Lnode *La_fast = La->next;
    Lnode *Lb_fast = Lb->next;
    Lnode *p = La;
    while (La_fast && Lb_fast){
        if (La_fast->data <= Lb_fast->data){
            p->next = La_fast;
            p = La_fast;
            La_fast = La_fast->next;
        } else{
            p->next = Lb_fast;
            p = Lb_fast;
            Lb_fast = Lb_fast->next;
        }
    }
    p->next = La_fast ? La_fast : Lb_fast;
    free(Lb);
}

時間複雜度為:O(min(La,Lb))

空間複雜度為:O(1)

案例

實現一元多項式加運算

\[Pa=10+5\cdot x-4\cdot x^2+3\cdot x^3+2\cdot x^4\\ Pb=-3+8\cdot x+4\cdot x^2-5\cdot x^4+7\cdot x^5-2\cdot x^6\\ Pc=Pa+Pb=7+13\cdot x+3\cdot x^3+-3\cdot x^4+7\cdot x^5+-2\cdot x^6 \]

有序表

固定版

#include <stdio.h>

int main()
{
    float Pa[] = {10,5,-4,3,2,0,0,0,0,5};
    float Pb[] = {-3,8,4,0,-5,7,-2,0,0,7};
    float Pc[] = {0,0,0,0,0,0,0,0,0,0};
    for (int i = 0; i < 9; ++i) {
        Pc[i] = Pa[i]+Pb[i];
    }
    Pc[9] = Pa[9]<Pb[9] ? Pb[9] : Pa[9];
    for (int j = 0; j < Pc[9]; ++j) {
        if (j == Pc[9]-1){
            printf("%0.1fX^%d",Pc[j],j);
        } else {
            printf("%0.1fX^%d+",Pc[j],j);
        }
    }
    return 0;
}

自定義版

#include <stdio.h>
#define PolynomialMax 20

int main()
{
    float Pa[PolynomialMax],Pb[PolynomialMax];
    for (int m = 0; m < PolynomialMax; ++m) Pa[m] = Pb[m] = 0;
    for (int i = 1; i < 3; ++i) {
        int q = 0;
        printf("多項式:%d\n", i);
        while (1) {
            float temp;
            printf("輸入指數為%d的係數:", q);
            scanf("%f", &temp);
            if (i == 1) {
                Pa[q] = temp;
                Pa[PolynomialMax - 1] = q + 1;
            } else {
                Pb[q] = temp;
                Pb[PolynomialMax - 1] = q + 1;
            }
            fflush(stdin);
            q++;
            printf("是否結束(Y/N)");
            char quit;
            scanf("%c", &quit);
            if (quit == 'Y' || q == PolynomialMax - 1) break;
        }
    }
    for (int j = 0; j < 2; ++j) {
        for (int k = 0; k < PolynomialMax; ++k) {
            if (j==0){
                if (k == Pa[PolynomialMax-1]-1){
                    printf("%0.2fX^%d",Pa[k],k);
                    printf("\n");
                    break;
                } else {
                    printf("%0.2fX^%d+",Pa[k],k);
                }
            } else {
                if (k == Pa[PolynomialMax-1]-1){
                    printf("%0.2fX^%d",Pb[k],k);
                    printf("\n");
                    break;
                } else {
                    printf("%0.2fX^%d+",Pb[k],k);
                }
            }
        }
    }
    float Pc[PolynomialMax];
    for (int n = 0; n < PolynomialMax; ++n) Pc[n] = 0;
    Pc[PolynomialMax-1] = Pa[PolynomialMax-1] < Pb[PolynomialMax-1] ? Pb[PolynomialMax-1] : Pa[PolynomialMax-1];
    for (int l = 0; l < Pc[PolynomialMax-1]; ++l) Pc[l] = Pa[l]+Pb[l];
    for (int i1 = 0; i1 < Pc[PolynomialMax-1]; ++i1) printf("%0.2fX^%d+",Pc[i1],i1);
    return 0;
}

稀疏多項式運算

順序表與連結串列

SparsePolynomial.h

//
// Created by admin on 2020/7/12.
//

#include <stdio.h>
#include <stdlib.h>
#ifndef DATASTRUCTURE_SPARSEPOLYNOMIAL_H
#define DATASTRUCTURE_SPARSEPOLYNOMIAL_H
#define MAXELEMLENGTH 20
typedef struct {
    int index;
    float coefficient;
}Polynomial;

typedef struct{
    Polynomial *elem;
    int length;
}SqList;

typedef struct LNode{
    Polynomial date;
    struct LNode *prior;
    struct LNode *next;
}LNode,*LinkList;

//建立線性表
SqList CreateSqList();
//新增項
int AddPolynomialSqList(SqList *L,Polynomial data);
//多項式相加
SqList UnionSqList(SqList *L,SqList *Q);
//建立雙向連結串列
LinkList CreateLNode();
//新增結點
LinkList AddPolynomialLNode(LinkList L,Polynomial data);
//多項式相加
LinkList UnionLNode(LinkList L,LinkList p);
#endif //DATASTRUCTURE_SPARSEPOLYNOMIAL_H

SParsePolunomial.c

//
// Created by admin on 2020/7/12.
//
#include "SparsePolynomial.h"

SqList CreateSqList(){
    Polynomial *polynomialList = (Polynomial *)malloc(sizeof(Polynomial) * MAXELEMLENGTH);
    if (polynomialList == NULL){
        exit(0);
    }
    SqList sqList;
    sqList.elem = polynomialList;
    sqList.length = 0;
    return sqList;
}

int AddPolynomialSqList(SqList *L,Polynomial data){
    if (L->length >= MAXELEMLENGTH){
        return 0;
    }
    L->elem[L->length] = data;
    L->length++;
    return 1;
}

SqList UnionSqList(SqList *L,SqList *Q){
    int LStart,QStart;
    LStart = QStart = 0;
    Polynomial *polynomialList = (Polynomial *)malloc(sizeof(Polynomial) * (L->length+Q->length));
    if (polynomialList == NULL){
        exit(0);
    }
    SqList sqList;
    sqList.elem = polynomialList;
    sqList.length = 0;
    while (LStart < L->length && QStart < Q->length){
        if (L->elem[LStart].index == Q->elem[QStart].index){
            Polynomial polynomial;
            polynomial.index = L->elem[LStart].index;
            polynomial.coefficient = L->elem[LStart++].coefficient + Q->elem[QStart++].coefficient;
            if (polynomial.coefficient != 0) {
                sqList.elem[sqList.length++] = polynomial;
            }
        } else if (L->elem[LStart].index < Q->elem[QStart].index){
            sqList.elem[sqList.length++] = L->elem[LStart++];
        } else if (L->elem[LStart].index > Q->elem[QStart].index){
            sqList.elem[sqList.length++] = Q->elem[QStart++];
        }
    }
    while (LStart < L->length){
        sqList.elem[sqList.length++] = L->elem[LStart++];
    }
    while (QStart < Q->length){
        sqList.elem[sqList.length++] = Q->elem[QStart++];
    }
    return sqList;
}

LinkList CreateLNode(){
    LinkList linkList = (LinkList)malloc(sizeof(LNode));
    if (linkList == NULL){
        exit(0);
    }
    linkList->prior = NULL;
    linkList->next = linkList;
    return linkList;
}

LinkList AddPolynomialLNode(LinkList L,Polynomial data){
    LinkList linkList = CreateLNode();
    linkList->date = data;
    linkList->prior = L;
    linkList->next = L->next;
    linkList->next->prior = linkList;
    L->next = linkList;
    return linkList;
}

LinkList UnionLNode(LinkList L,LinkList P){
    LinkList SL = L->next->next;
    LinkList SP = P->next->next;
    LinkList SS = CreateLNode();
    while (1){
        if (SL->date.index == SP->date.index){
            Polynomial polynomial;
            polynomial.index = SL->date.index;
            polynomial.coefficient = SL->date.coefficient + SP->date.coefficient;
            if (polynomial.coefficient != 0){
                SS = AddPolynomialLNode(SS,polynomial);
            }
            SL = SL->next;
            SP = SP->next;
        } else if (SL->date.index < SP->date.index){
            SS = AddPolynomialLNode(SS,SL->date);
            SL = SL->next;
        } else if (SL->date.index > SP->date.index){
            SS = AddPolynomialLNode(SS,SP->date);
            SP = SP->next;
        }
        if (SL == L->next || SP == P->next){
            break;
        }
    }
    while (SL != L->next){
        SS = AddPolynomialLNode(SS,SL->date);
        SL = SL->next;
    }
    while (SP != P->next){
        SS = AddPolynomialLNode(SS,SP->date);
        SP = SP->next;
    }
    return SS;
}

main.c

#include <stdio.h>
#include "SparsePolynomial.h"
int main()
{
    int indexL[] = {0,1,2,3,4};
    int indexQ[] = {0,1,2,4,5,6};
    float coefficientL[] = {10,5,-4,3,2};
    float coefficientQ[] = {-3,8,4,-5,7,-2};
    Polynomial polynomial;

    printf("稀疏多項式線性表順序表實現相加:");
    SqList sqListL;
    SqList sqListQ;
    sqListL = CreateSqList();
    sqListQ = CreateSqList();
    for (int i = 0; i < sizeof(indexL)/sizeof(int); ++i) {
        polynomial.index = indexL[i];
        polynomial.coefficient = coefficientL[i];
        AddPolynomialSqList(&sqListL,polynomial);
    }
    for (int j = 0; j < sizeof(indexQ)/sizeof(int); ++j) {
        polynomial.index = indexQ[j];
        polynomial.coefficient = coefficientQ[j];
        AddPolynomialSqList(&sqListQ,polynomial);
    }
    SqList sqList;
    sqList = UnionSqList(&sqListL,&sqListQ);
    for (int k = 0; k < sqList.length; ++k) {
        if (k == sqList.length-1){
            printf("%.0f*X^%d",sqList.elem[k].coefficient,sqList.elem[k].index);
        } else{
            printf("%.0f*X^%d+",sqList.elem[k].coefficient,sqList.elem[k].index);
        }
    }
    printf("\n");
    printf("稀疏多項式線性表雙向連結串列(尾指標)實現相加:");
    LinkList linkListL,linkListQ;
    linkListL = CreateLNode();
    linkListQ = CreateLNode();
    for (int i = 0; i < sizeof(indexL)/sizeof(int); ++i) {
        polynomial.index = indexL[i];
        polynomial.coefficient = coefficientL[i];
        linkListL = AddPolynomialLNode(linkListL,polynomial);
    }
    for (int j = 0; j < sizeof(indexQ)/sizeof(int); ++j) {
        polynomial.index = indexQ[j];
        polynomial.coefficient = coefficientQ[j];
        linkListQ = AddPolynomialLNode(linkListQ,polynomial);
    }
    LinkList  linkList;
    linkList = UnionLNode(linkListL,linkListQ);
    LinkList temp = linkList->next->next;
    while (1){
        if (temp == linkList){
            printf("%.0f*X^%d",temp->date.coefficient,temp->date.index);
        }
        else{
            printf("%.0f*X^%d+",temp->date.coefficient,temp->date.index);
        }
        temp = temp->next;
        if (temp == linkList->next){
            break;
        }
    }
    return 0;
}

圖書資訊系統

順序表與連結串列

LibraySystem.h

//
// Created by admin on 2020/7/12.
//

#include <stdio.h>
#include <stdlib.h>
#ifndef DATASTRUCTURE_LIBRARYSYSTEM_H
#define DATASTRUCTURE_LIBRARYSYSTEM_H
#define MAXBOOKSNUMBER 100
typedef struct {
    char id[20];
    char name[50];
    float price;
}Book;

typedef struct {
    Book *elem;
    int length;
}SqList;

typedef struct LNode{
    Book date;
    struct LNode *prior;
    struct LNode *next;
}LNode,*LinkList;

//建立線性表
SqList CreateSqList();
//新增項
int AddPolynomialSqList(SqList *L,Book data);
//多項式相加
SqList UnionSqList(SqList *L,SqList *Q);
//建立雙向連結串列
LinkList CreateLNode();
//新增結點
LinkList AddPolynomialLNode(LinkList L,Book data);
//多項式相加
LinkList UnionLNode(LinkList L,LinkList p);
#endif //DATASTRUCTURE_LIBRARYSYSTEM_H

LibraySystem.c

//
// Created by admin on 2020/7/12.
//
#include "LibrarySystem.h"

SqList CreateSqList(){
    Book *book = (Book *)malloc(sizeof(Book) * MAXBOOKSNUMBER);
    if (book == NULL){
        exit(0);
    }
    SqList sqList;
    sqList.elem = book;
    sqList.length = 0;
    return sqList;
}

int AddPolynomialSqList(SqList *L,Book data){
    if (L->length >= MAXBOOKSNUMBER){
        return 0;
    }
    L->elem[L->length] = data;
    L->length++;
    return 1;
}

LinkList CreateLNode(){
    LinkList linkList = (LinkList)malloc(sizeof(LNode));
    if (linkList == NULL){
        exit(0);
    }
    linkList->prior = NULL;
    linkList->next = linkList;
    return linkList;
}

LinkList AddPolynomialLNode(LinkList L,Book data){
    LinkList linkList = CreateLNode();
    linkList->date = data;
    linkList->prior = L;
    linkList->next = L->next;
    linkList->next->prior = linkList;
    L->next = linkList;
    return linkList;
}

main.c

#include <stdio.h>
#include <string.h>
#include "LibrarySystem.h"
int main()
{
    SqList sqList;
    sqList = CreateSqList();
    char ISBN[5][20] = {"9787302257642","9787302257643","9787302257644",
                        "9787302257654","9787302257656"};
    char Name[5][50] = {"資料庫原理","計算機網路","資料結構","編譯原理","計算機組成原理"};
    float Price[5] = {25,35.5,45,78.5,99};
    for (int i = 0; i < 5; ++i) {
        Book book;
        strcpy(book.id,ISBN[i]);
        strcpy(book.name,Name[i]);
        book.price = Price[i];
        AddPolynomialSqList(&sqList,book);
    }
    LinkList linkList;
    linkList = CreateLNode();
    for (int j = 0; j < sqList.length; ++j) {
        printf("%s\t%s\t%.2f\n",sqList.elem[j].id,sqList.elem[j].name,sqList.elem[j].price);
        linkList = AddPolynomialLNode(linkList,sqList.elem[j]);
    }
    LinkList temp = linkList->next->next;
    while (1){
        printf("%s\t%s\t%.2f\n",temp->date.id,temp->date.name,temp->date.price);
        temp = temp->next;
        if (temp == linkList->next){
            break;
        }
    }
    return 0;
}