C - linklist 用法

使用 linklist 的方式儲存資料,可用來搜尋... 


定義


LINKLIST *ll_init(void); // linklist 初始化
LINKLIST *ll_append(LINKLIST *list, void *newdata); // 從後面附加資料,可用 ll_add 取代
LINKLIST *ll_prepend(LINKLIST *list, void *newdata); // 從前面插入資料,可用 ll_insert 取代
void *ll_delete(LINKLIST *list, void *key, AD_COMPARE_FUNC *match); // 刪除資料
void *ll_find(LINKLIST *list, void *key, AD_LOCK lock_f, AD_COMPARE_FUNC *match); // 找資料
void *ll_get(LINKLIST *list, void **node, AD_LOCK lock_f); // 依序取資料
void ll_free(LINKLIST *list); // 釋放 linklist
AD_BOOLEAN ll_traverse(LINKLIST *list, AD_LOCK lock_f, AD_TRAV_FUNC *travFunc, void *param);
unsigned ll_count(LINKLIST *list); // 返回目前筆數
AD_BOOLEAN ll_empty(LINKLIST *list); // 是否為空陣列
void *ll_tail(LINKLIST *list); // 回傳最後一筆資料
void *ll_head(LINKLIST *list); // 回傳第一筆資料
int ll_swapline(LINKLIST *list, void *key1, void *key2, AD_LOCK lock_f, AD_COMPARE_FUNC *match);



用法

新增資料


struct LL_DATA { // 要丟進 linklist 的資料內容
char *name;
int val;
};
static AD_RELATION data_compare(void *v1, void *v2) // key 的判斷方式
{
struct LL_DATA *data1 = (struct LL_DATA *) v1;
struct LL_DATA *data2 = (struct LL_DATA *) v2;
return !strcmp(data1->name, data2->name) ? AD_EQUAL : AD_LESS_THAN;
}
void data_replace(LINKLIST *ll, char *name, int val) { // 增加或修改值
struct LL_DATA llData, *_llData;
memset(&llData, '\0', sizeof(struct LL_DATA));
llData.name = name;
// 先找看看是不是已經加入一樣的key, 判斷方式如 data_compare
if ((_llData = ll_find(ll, (void *)&llData, AD_NEED_LOCK, data_compare))) {
// 已加過,就直接改值
_llData->val = val;
} else if((_llData = calloc(1, sizeof(struct LL_DATA)))) {
// 沒加過,添加進 linklist 結構裡
_llData->name = strdup(llData.name);
_llData->count = val;
ll_append(ll, _llData);
}
}
void data_free(LINKLIST *ll) { // 逐筆資料抓出來釋放記憶體
struct LL_DATA *_llData;
void *node = NULL;
while((_llData = ll_get(ll, &node, AD_NEED_LOCK))) {
free(_llData->name);
free(_llData);
}
}
int main(int argc, char **argv) {
LINKLIST *ll = ll_init(); // 初始化

data_add(ll, "aaa", 50); // 增加或修改值
data_add(ll, "bbb", 50); // 增加或修改值

data_free(ll); // 結束前要把 ll 的資料,逐筆釋放
ll_free(ll); // 最後再釋放 ll
}


抓取特定資料


void getData(LINKLIST *ll, char *name) {
struct LL_DATA llData, *_llData;
memset(&llData, '\0', sizeof(struct LL_DATA));
llData.name = name;
if ((_llData = ll_find(ll, &llData, AD_NEED_LOCK, data_compare))) {
// 有找到這個key的話,會進這裡

}
}

註:data_compare 可以傳入跟新增時的 func 不同。(依照想法找不同的key)

抓取特定資料,並刪除


void delData(LINKLIST *ll, char *name) {
struct LL_DATA llData, *_llData;
memset(&llData, '\0', sizeof(struct LL_DATA));
llData.name = name;
if ((_llData = ll_delete(ll, &llData, data_compare))) {
// 有找到這個key的話,會進這裡,並從 linklist 移除

// 最後做完一樣要釋放記憶體
free(_llData->name);
free(_llData);
}
}

 註:data_compare 可以傳入跟新增時的 func 不同。(依照想法找不同的key)


歷遍所有資料

1. 使用 ll_get

void data_free(LINKLIST *ll) { // 逐筆資料抓出來釋放記憶體
struct LL_DATA *_llData;
void *node = NULL; // 重覆使用這個變數,一定要指成 NULL,才會再從頭開始哦
while((_llData = ll_get(ll, &node, AD_NEED_LOCK))) {
free(_llData->name);
free(_llData);
}
}

2. 使用 ll_traverse

AD_BOOLEAN freeEntry(void *data, void *param)
{
struct LL_DATA *data1 = (struct LL_DATA *) data;
struct LL_DATA *data2 = (struct LL_DATA *) param;
if(data1) {
free(data1->name);
free(data1);
return AD_FALSE;
}

return AD_TRUE;
}
void data_free(LINKLIST *ll) {
struct LL_DATA llData;
ll_traverse(ll, AD_NEED_LOCK, freeEntry, (void *)&llData);
}




後面附上這個 lib 的原始碼
linklist.h 原始碼
linklist.c 原始碼
ll_queue.c 原始碼
(這原始碼已不知道從何來的,侵權請告知,我會將它刪除,謝謝。也很感謝這位原作者)


沒有留言:

張貼留言