首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C 語言線性表順序儲存結構完整實作:動態擴容、增刪查改

     編輯:關於C語言

一、抽象資料型別 (ADT) 定義

// Sqlist.h
#ifndef SQLIST_H
#define SQLIST_H

#include 
#include 

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

typedef int Status;
typedef int ElemType; // 可改為任意型別

#define LIST_INIT_SIZE 100
#define LIST_INCREMENT 10

typedef struct {
    ElemType *elem;    // 資料基址
    int length;        // 當前長度
    int listSize;      // 當前分配容量
} SqList;

// 介面宣告
Status InitList(SqList *L);
Status ListInsert(SqList *L, int pos, ElemType e);
Status ListDelete(SqList *L, int pos, ElemType *e);
Status ListGet(SqList *L, int pos, ElemType *e);
int LocateElem(SqList L, ElemType e);
Status ListTraverse(SqList L, void (*visit)(ElemType));
Status ClearList(SqList *L);
Status DestroyList(SqList *L);
int ListLength(SqList L);
int ListEmpty(SqList L);

#endif

二、核心操作實作

初始化與銷毀

Status InitList(SqList *L) {
    if (!L) return ERROR;
    L->elem = malloc(LIST_INIT_SIZE * sizeof(ElemType));
    if (!L->elem) return ERROR;
    L->length = 0;
    L->listSize = LIST_INIT_SIZE;
    return OK;
}

Status DestroyList(SqList *L) {
    if (!L || !L->elem) return ERROR;
    free(L->elem);
    L->elem = NULL;
    L->length = L->listSize = 0;
    return OK;
}

動態擴容插入

Status ListInsert(SqList *L, int pos, ElemType e) {
    if (!L || !L->elem) return ERROR;
    if (pos < 1 || pos > L->length + 1) return ERROR; // 位置合法性
    
    // 滿容擴容
    if (L->length >= L->listSize) {
        ElemType *newBase = realloc(L->elem, (L->listSize + LIST_INCREMENT) * sizeof(ElemType));
        if (!newBase) return ERROR;
        L->elem = newBase;
        L->listSize += LIST_INCREMENT;
    }
    
    // 從尾端向前搬移
    ElemType *p = L->elem + pos - 1;        // 插入位置
    ElemType *q = L->elem + L->length - 1;  // 最後元素
    for (; q >= p; q--) *(q + 1) = *q;
    
    *p = e;
    L->length++;
    return OK;
}

刪除與查找

Status ListDelete(SqList *L, int pos, ElemType *e) {
    if (!L || !L->elem || !e) return ERROR;
    if (L->length == 0) return ERROR;
    if (pos < 1 || pos > L->length) return ERROR;
    
    ElemType *p = L->elem + pos - 1;
    *e = *p;
    ElemType *q = L->elem + L->length - 1;
    for (++p; p <= q; p++) *(p - 1) = *p; // 後續元素前移
    L->length--;
    return OK;
}

int LocateElem(SqList L, ElemType e) {
    if (!L.elem) return 0;
    for (int i = 0; i < L.length; i++)
        if (L.elem[i] == e) return i + 1; // 回傳 1-based 位置
    return 0; // 未找到
}

遍歷與清空

Status ListTraverse(SqList L, void (*visit)(ElemType)) {
    if (!L.elem) return ERROR;
    for (int i = 0; i < L.length; i++) visit(L.elem[i]);
    return OK;
}

Status ClearList(SqList *L) {
    if (!L) return ERROR;
    L->length = 0; // 邏輯清空,記憶體保留供下次使用
    return OK;
}

三、測試驗證主程式

#include "Sqlist.h"

void printElem(ElemType e) { printf("%d ", e); }

int main() {
    SqList L;
    InitList(&L);
    
    // 測試插入
    for (int i = 1; i <= 10; i++) ListInsert(&L, i, i * 10);
    printf("Length: %d\n", ListLength(L));
    ListTraverse(L, printElem); putchar('\n');
    
    // 測試指定位置插入
    ListInsert(&L, 5, 999);
    ListTraverse(L, printElem); putchar('\n');
    
    // 測試刪除
    ElemType delVal;
    ListDelete(&L, 3, &delVal);
    printf("Deleted: %d\n", delVal);
    ListTraverse(L, printElem); putchar('\n');
    
    // 測試查找
    printf("Locate 999: %d\n", LocateElem(L, 999));
    printf("Locate 888: %d\n", LocateElem(L, 888));
    
    DestroyList(&L);
    return 0;
}

四、時空複雜度分析

操作平均時間最壞時間空間
初始化O(1)O(1)O(1)
插入O(n)O(n)O(1) 擴容時 O(n)
刪除O(n)O(n)O(1)
按位查找O(1)O(1)O(1)
按值查找O(n)O(n)O(1)
遍歷O(n)O(n)O(1)

五、順序表 vs 鏈表 選型指南

  • 順序表優勢:隨機存取 O(1)、記憶體連續 Cache 友善、無指標開銷、適合頻繁查找/遍歷、中小規模資料。
  • 鏈表優勢:插入刪除 O(1) (已知位置)、動態擴容無複製、適合頻繁頭尾操作、大型可變長資料。
  • 實務建議:現代 CPU Cache 效應下,中小規模 ( < 10^5 ) 順序表通常比鏈表快;需頻繁中間插刪大量資料才考慮鏈表或平衡樹。

六、常見錯誤避坑

  1. 位置參數混淆:介面通常用 1-based,內部陣列 0-based,轉換務必小心。
  2. realloc 失敗時原指標仍有效,必須用暫存變數接收回傳值再賦值。
  3. 刪除後未將釋放指標置 NULL (若為指標型別),導致野指標。
  4. 傳結構體而非指標給修改操作,導致修改無效 (值拷貝)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved