快速學習C語言四: 造輪子,ArrayList

高級語言裏的列表是最經常使用的數據結構,在C裏造個輪子玩玩,C沒有泛型,先用int練習。git

Collection的ADT通常有hasnext,next,add, remove操做,List通常還加了removeat, insert等,而後Stack有push和pop,Queue有enqueue和dequeue。列表有種實現, ArrayList和LinkedList,整體來講ArrayList更經常使用一些,就先用數組實現個列表。github

ArrayList在末尾的添加和刪除仍是挺快的(O(1)),因此當棧來用挺好,Push和Pop都在末尾。 當隊列的話,Enqueue在數組頭部放入元素,全部右邊的元素都要向右移動(O(N)),比較耗 時,不如LinkedList。另外獲取指定索引數據或設置指定索引的數據是O(1)複雜度, 比LinkedList快,若是要想查看是否有指定數據,或刪除指定數據,要掃描全表,複雜度 是O(N)。哦,刪除指定位置的數據複雜度也是O(N), 由於刪除後右邊的數據要所有向 左移動。數組

能夠開始了,首先定義一個結構來保存狀態數據結構

struct arr_list {
    int * arr;      // 內部數組
    int index;      // 實際數據大小
    int size;       // 預分配空間大小
};

 

建立一個array list函數

struct arr_list* create_arr_list(n) {
    if (n < 1) {
        n = 10;
    }
    struct arr_list *arr = (struct arr_list*)malloc(sizeof(struct arr_list));
    arr->arr = (int*)malloc(sizeof(int) * n);
    arr->size = n;
    arr->index = 0;
    return arr;
}

 

空間不足時自動擴容,默認策略是空間不夠時申請雙倍大小空間, 而後把原有數據拷貝到 新空間,並把原有空間釋放掉, 該函數通常是新增元素前調用,因此判斷條件是當實際 所用空間已經等於或大於(應該不可能)預分配空間時擴容。測試

static void expand_space(struct arr_list *arr) {
    int *tmp, i, *p, *q;

    if (arr->index >= arr->size) {
        tmp = (int *)malloc(sizeof(int) * arr->size * 2);
        p = arr->arr;
        q = tmp;
        for (i = 0; i < arr->index; i++) {
            *q++ = *p++;
        }
        free(arr->arr);
        arr->arr = tmp;
        arr->size = arr->size * 2;
    }
}

 

在指定位置插入新元素,現有元素向右移,O(N)spa

int list_insert(struct arr_list *arr, int index, int obj) {
    int i;

    if (index < 0 || index > arr->index) {
        return -1;
    }
    expand_space(arr);

    for (i = arr->index; i > index ; i--) {
        arr->arr[i] = arr->arr[i - 1];
    }
    arr->arr[index] = obj;
    arr->index++;
    return 0;
}

 

在array list 末尾插入數據, O(1)code

int list_push(struct arr_list *arr, int obj) {
    return list_insert(arr, arr->index, obj);
}

 

刪除指定位置的數據,O(N), 刪除數據後,全部數據向左移動blog

int list_removeat(struct arr_list *arr, int index) {
    int i;
    if (index < 0 || index >= arr->index) {
        return -1;
    }
    for (i = index; i < arr->index - 1; i++) {
        arr->arr[index] = arr->arr[index + 1];
    }
    arr->index--;
    return 0;
}

 

移除並返回末尾的數據, O(1)索引

int list_pop(struct arr_list *arr) {
    return list_removeat(arr, arr->index - 1);
}

 

判斷 array list裏是否包含某個數據, O(N)

int list_index(const struct arr_list *arr, int obj) {
    int i;
    for (i = 0; i < arr->index; i++) {
        if (arr->arr[i] == obj) {
            return i;
        }
    }
    return -1;
}

 

刪除某個數據項,O(N), 只刪第一次出現的位置, 刪除後全部數據向左移動

int list_remove(struct arr_list *arr, int obj) {
    int i, index;
    index = list_index(arr, obj);
    if (index != -1) {
        for (i = index; i < arr->index - 1; i++) {
            arr->arr[i] = arr->arr[i + 1];
        }
        arr->index--;
    }
    return index;
}

 

釋放一個array list的內存

int free_arr_list(struct arr_list *arr){
    free(arr->arr);
    free(arr);
    return 0;
}

 

從頭打印一個arr list

void print_arr_list(const struct arr_list *arr) {
    int i, t;
    printf("size=%d,index=%d\n", arr->size, arr->index);
    for (i = 0; i < arr->index; i++) {
        list_get(arr, i, &t);
        printf("list[%d]=%d\n", i, t);
    }
}

 

最後總體測試一下

int main(void)
{
    struct arr_list *arr;
    int r;

    arr = create_arr_list(3);
    printf("list push: 5, 6, 7\n");
    list_push(arr, 5);
    list_push(arr, 6);
    list_push(arr, 7);
    print_arr_list(arr);

    printf("list push: 8, will auto expand\n");
    list_push(arr, 8);
    print_arr_list(arr);

    printf("list remove at 2\n");
    list_removeat(arr, 2);
    print_arr_list(arr);

    printf("list pop \n");
    list_pop(arr);
    print_arr_list(arr);

    printf("list insert 0\n");
    list_insert(arr, 0, 3);
    print_arr_list(arr);

    r = list_index(arr, 3);
    printf("list index 3:%d\n", r);
    r = list_index(arr, 7);
    printf("list index 7:%d\n", r);

    printf("list remove 3\n");
    list_remove(arr, 3);
    print_arr_list(arr);

    printf("list set index 0 = 3\n");
    list_set(arr, 0, 3);
    print_arr_list(arr);

    free_arr_list(arr);
    return 0;
}

 

小結

用C實現一下高級語言裏經常使用的數據結構,能夠對它們有更深的理解。

相關文章
相關標籤/搜索