順序表主要操作集的實現(xiàn)

  • 相關宏定義及數(shù)據(jù)類型的別名定義

    #define LIST_INIT_SIZE 10   // 初始化順序表的空間分配量
    #define LIST_INCREMENT 10   // 順序表空間用完后的分配增量
    
    #define OK 1    // 函數(shù)正常返回
    #define ERROR -1    // 函數(shù)異常返回
    
    #define EMPTY 0 // 表空
    #define NOT_EMPTY 1 // 表不空
    
    typedef int ElemType;   // 元素類型
    typedef int Status; // 狀態(tài)(用作返回值類型)
    typedef int Length; // 長度
    typedef int Position; // 位序
    
    
  • 結構定義

    typedef struct {
        ElemType *elem; //  存儲空間基址(首地址)
        int length;     //  已存儲的元素個數(shù)
        int list_size;  //  當前分配的存儲量(目前可存儲元素的個數(shù))
    } SqList;
    
  • InitList():構造一個空表

    Status InitList_Sq(SqList *L) {
    
        // 動態(tài)分配存儲空間,返回已分配空間的首地址
        L->elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
    
        // 如果分配后返回地址為空 說明分配失敗
        if (!L->elem)   
            exit(ERROR);
    
        L->length = 0; // 空表長度為0
        L->list_size = LIST_INIT_SIZE; // 當前分配量即為初始分配量
    
        return OK;
    }
    
  • DestroyList(): 銷毀線性表

    Status DestroyList_Sq(SqList *L) {
    
        // 如果傳入的線性表空間首地址為空 說明初始化時空間分配異常 
        // 則直接異常終止進程 之后的代碼將不被執(zhí)行
        if (!L->elem)   
            exit(EXIT_FAILURE);
        
        // 釋放 L->elem 指向的內存
        free(L->elem);
    
        L->elem = NULL;
        L->length = 0;
        L->list_size = 0;
    
        return OK;
    }
    
  • ClearList():重置為空表

    Status ClearList_Sq(SqList *L) {
        if (!L->elem)   
            return ERROR;
    
        L->length = 0;
        return OK;
    }
    
  • ListEmpty(): 檢測該表是否為空

    Status ListEmpty_Sq(SqList *L) {
        return (L->length > 0) ? NOT_EMPTY : EMPTY;
    }
    
  • GetLength(): 獲取順序表中元素的個數(shù)

    Length GetLength_Sq(SqList *L) {
        return L->length;
    }
    
  • GetElem(): 用 e 返回 L 中下標為 i 的元素的值

    Status GetElem_Sq(SqList *L, int i, ElemType *e) {
        // 若空間分配異?;虮碇袩o元素 異常返回
        if (!L->elem || L->length < 1)
            return ERROR;
    
        *e = L->elem[i];
        return OK;
    }
    
  • LocateElem(): 返回表中第一個與 e 值滿足關系 compare() 的元素的位序(非下標)

Position LocateElem_Sq(SqList *L, ElemType e, Status((*compare)(ElemType e1, ElemType e2))) {
    // 若順序表為空 返回錯誤狀態(tài)
    if (ListEmpty_Sq(L) == EMPTY)   
        return ERROR;

    for (int i = 0; i < L->length; ++i) {
        // 將第 i 個元素與 e 值作為參數(shù)傳入 compare(),根據(jù)返回值判斷是否滿足該關系,若是,則返回位序,否則繼續(xù)往下遍歷
        if ((*compare)(e, L->elem[i]) == OK)
            return i + 1;
        else
            continue;
    }
    
    return 0;
}
  • compare(): 這里使用相等關系表示 compare() 函數(shù)

    Status Equal(ElemType e1, ElemType e2) {
        return (e1 == e2) ? OK : ERROR;
    }
    
    • 調用舉例
    int main() {
        ...
        // 返回表中第一個值為 8 的元素的位序
        int pos = LocateElem_Sq(&L, 8,  Equal);
        
        // 例如對于順序表:{3, 8, 6, 0, 9, 7, 4, 11},此時 pos 的值應為 2
        printf("%d", pos);
        ...
    }
    
  • GetKth(): 獲取第 k(位序,非下標) 個元素

    Status GetKth(SqList *L, int k, ElemType *e) {
        // 1<=k<=length
        if (k < 1 || k > L->length) {
            return ERROR;
        } else {
            *e = L->elem[k - 1];
            return OK;
        }
    }
    
  • PriorElem(): 獲取 curElem 的前驅

    ElemType PriorElem_Sq(SqList *L, ElemType curElem, ElemType *pre_e) {
        // 先找到當前元素的位序
        int locateRes = LocateElem_Sq(L, curElem, Equal);
    
        // ERROR:表空; 1: 位序為1,第1個元素無前驅; 0: 表中未找到當前元素
        if (locateRes == ERROR || locateRes == 1 || locateRes == 0) {
            if (locateRes == 1) {
                printf("\nERROR: 第一個元素無前驅!");
            }
            else if (locateRes == 0) {
                printf("\nERROR: 目標元素: %d 不存在!", curElem);
            }
    
            return ERROR;
        }
    
        // 成功找到存在前驅的 curElem
        else {
            //  將位序為 locateRes - 1 的元素(即curElem的前驅)值寫入 pre_e
            if (GetKth(L, locateRes - 1, pre_e) != ERROR) {
                return OK;
            }
            else {
                printf("\nERROR: 未找到指定元素: %d 的前驅!", curElem);
                return ERROR;
            }
        }
    }
    
  • NextElem(): 獲取 curElem 的后繼

    ElemType NextElem_Sq(SqList *L, ElemType curElem, ElemType *next_e) {
        int locateRes = LocateElem_Sq(L, curElem, Equal);
    
        // ERROR:表空; 1: 位序為length,最后1個元素無后繼; 0: 表中未找到當前元素
        if (locateRes == ERROR || locateRes == L->length || locateRes == 0) {
            if (locateRes == L->length) {
                printf("\nERROR: 最后一個元素無后繼!");
            }
            else if (locateRes == 0) {
                printf("\nERROR: 目標元素: %d 不存在!", curElem);
            }
            return ERROR;
        }
        else {
            // 將位序為 locateRes + 1 的元素(即curElem的后繼)值寫入 next_e
            if (GetKth(L, locateRes + 1, next_e) != ERROR) {
                return OK;
            }
            else {
                printf("\nERROR: 未找到指定元素: %d 的前驅!", curElem);
                return ERROR;
            }
        }
    }
    
  • 調用舉例:查看表中所有元素的前驅與后繼

    int main () {
        ...
        
        for (int i = 0; i < L.length; i++) {
            // cur_e 為當前遍歷的元素
            ElemType cur_e = L.elem[i];
            
            // pre_e, next_e 分別表示指向前驅和后繼元素所占內存空間的地址,均為臨時量,用完需要釋放
            ElemType *pre_e = (ElemType *)malloc(sizeof(ElemType));
            ElemType *next_e = (ElemType *)malloc(sizeof(ElemType));
            
            // 將 cur_e 的前驅元素的值寫入 pre_e
            if (PriorElem_Sq(&L, cur_e, pre_e) == ERROR) {
                *pre_e = -1;
            }
            
            // 將 cur_e 的后繼元素的值寫入 next_e
            if (NextElem_Sq(&L, cur_e, next_e) == ERROR) {
                *next_e = -1;
            }
            
            // 輸出 cur_e, pre_e, next_e
            printf("\npreElem: %d\ncurElem: %d\nnextElem: %d\n", *pre_e, cur_e, *next_e);
            
            // 釋放動態(tài)空間
            free(pre_e);
            free(next_e);
        }
        
        ...
    }
    
    
  • ListInsert(): 在表中第 i 個元素之前插入元素 e

    Status ListInsert_Sq(SqList *L, int i, ElemType e) {
        //  i = 0: 在表頭插入元素, i = length: 在表尾插入元素,均合法,除此之外的都不合法
        if (i < 0 || i > L->length) {
            return ERROR;
        }
    
        //  若空間不足,需增大空間分配量
        if (L->length >= L->list_size) {
            ElemType *newbase;
            newbase = (ElemType*)realloc(L->elem, (LIST_INIT_SIZE + LIST_INCREMENT) * sizeof(ElemType));
            if (!newbase)   
                exit(EXIT_FAILURE);
                
            L->elem = newbase;
            L->list_size += LIST_INCREMENT;
        }
    
        //  從被插入的元素位置起,至表尾元素止,整體移動
        ElemType *q = &L->elem[i];
        ElemType *p = &L->elem[L->length - 1];
    
        // 從后向前逐個進行值的遷移 為新值的插入騰出一個元素所需的空間
        while (p >= q) {
            *(p + 1) = *p;
            --p;
        }
        
        *q = e; // 給目標插入位置賦值
        ++L->length;
    
        return OK;
    }
    
  • ListDelete(): 刪除指定下標的元素,并返回它的值

    Status ListDelete_Sq(SqList *L, int i, ElemType *e) {
        if (ListEmpty_Sq(L) == EMPTY)   return ERROR;
        if (i < 0 || i > L->length - 1) return ERROR;
    
        *e = L->elem[i];    // 目標刪除元素的值
        
        ElemType *q = &L->elem[i + 1];  // 目標刪除位置的后一個
        ElemType *p = &L->elem[L->length - 1];  // 表尾位置
    
        // 從前往后進行元素的逐個遷移
        while (q <= p) {
            *(q - 1) = *q;
            q++;
        }
        --L->length;
        
        return *e;
    }
    
  • ListTraverse(): 對表中每個元素進行遍歷

    Status ListTraverse_Sq(SqList *L, Status((*visit)(ElemType *curElem))) {
        if (ListEmpty_Sq(L) == EMPTY)
            return ERROR;
    
        for (int i = 0; i < L->length; ++i) {
            if ((*visit)(&L->elem[i]) == ERROR) {
                exit(EXIT_FAILURE);
            }
        }
        printf("\n");
        return OK;
    }
    
  • visit(): 這里使用打印輸出元素的值表示對單個元素的訪問

    Status PrintElem(ElemType *curElem) {
        if (!curElem)
            return ERROR;
    
        printf("%d ", *curElem);
        return OK;
    }
    
    • 調用舉例
    int main() {
        ...
        // 以 PrintElem 作為 Visit 方法遍歷順序表 L,程序將打印輸出 L 中每個元素的值
        ListTraverse_Sq(&L, PrintElem);
        ...
    }
    
  • AssignElem(): 自定義表長并為各元素賦值

    Status AssignElem_Sq(SqList *L, int *assign_size) {
        // 傳入的表還未分配內存空間,錯誤
        if (!L->elem)   
            exit(EXIT_FAILURE);
    
        printf("Input the assignment size: ");
    
        // 欲賦值的個數(shù),即表長
        scanf_s("%d", assign_size, 1); 
    
        // 欲賦值的個數(shù)大于當前已有的空間,錯誤
        if (*assign_size > L->list_size)    
            exit(EXIT_FAILURE);     
    
        // 依次為各元素賦值
        for (int i = 0; i < *assign_size; ++i) {
            scanf_s("%d", &L->elem[i], 1);
            L->length++;
        }
    
        return OK;
    }
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內容