靜態記憶體分配-連結串列管理(1)單向量表講解
阿新 • • 發佈:2019-01-10
單向連結串列
單向量表有頭節點 和節點組成,頭節點主要是管理連結串列使用,節點組成資料。
資料結構
**last指向尾節點的Next指標,在節點尾部插入節點時,直接調整頭節點的last內容的指向即可在尾部插入。first指標指向連結串列的首節點。
value是資料,Next指向下一個節點。
連結串列操作
連結串列成員變數定義
成員變數主要有頭結點和節點,頭結點不是真正的有效資料,主要是利於連結串列的插入,遍歷等,節點是連結串列中主要的資料。
程式碼
定義節點
#define SIMPLEQ_ENTRY(type) \ struct { \ struct type *sqe_next; /* next element */ \ }
上述程式碼定義了節點中的Next指標域,type是連結串列的型別,例如連結串列節點定義如下:
struct items_type{
SIMPLEQ_ENTRY(items_type) field;
u8 value;
};
上述程式碼定義了一個連結串列節點型別,可使用該型別定義一個節點。例如
struct items_type node0 = {.value = 0}; struct items_type node1 = {.value = 1}; struct items_type node2 = {.value = 2}; struct items_type node3 = {.value = 3};
定義了三個節點。
#define SIMPLEQ_HEAD(name, type) \
struct name { \
struct type *sqh_first; /* first element */ \
struct type **sqh_last; /* addr of last next element */ \
}
上述程式碼定義了連結串列的頭節點。name為頭結點的名字,type為節點的型別,例子
SIMPLEQ_HEAD(head, items_type) list_head;
上述程式碼定義了名為 list_head的頭節點。
API
#define SIMPLEQ_ENTRY(type)
定義節點型別,型別名為type。
#define SIMPLEQ_HEAD(name, type)
定義頭節點,name為頭節點名,type為節點型別。
#define SIMPLEQ_HEAD_INITIALIZER(head)
#define SIMPLEQ_INIT(head)
兩個API作用相同,頭節點初始化。
#define SIMPLEQ_INSERT_HEAD(head, elm, field)
在連結串列首部插入一個節點,head為頭節點,elm為要插入的元素,filed為指標域,與節點型別有關,上面的例子中型別的指標域名為filed,以後的使用過程也必須用filed。
#define SIMPLEQ_INSERT_TAIL(head, elm, field)
在連結串列的尾部插入一個節點,head為頭節點,lem為要插入的元素,filed見上述解釋。
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field)
在連結串列的listelm節點後插入elm節點。其他見上述解釋。
#define SIMPLEQ_REMOVE_HEAD(head, field)
移除連結串列中的首節點。
#define SIMPLEQ_REMOVE(head, elm, type, field)
SIMPLEQ_REMOVE(&list_head, &node1, items_type, field);
移除連結串列中的elm節點,type為節點的型別。
#define SIMPLEQ_FOREACH(var, head, field)
SIMPLEQ_FOREACH(ptype, &list_head, field) {
printf("value = %4d,", ptype->value);
}
遍歷連結串列,例子如上。
#define SIMPLEQ_EMPTY(head)
連結串列是否為空。
#define SIMPLEQ_FIRST(head)
找出首節點。
#define SIMPLEQ_NEXT(elm, field)
找出連結串列中某個元素的下一個元素。
圖形說明
上圖為單向連結串列說明
測試程式碼
#include "queue.h"
#include "types.h"
#include "stdio.h"
struct items_type{
SIMPLEQ_ENTRY(items_type) field;
u8 value;//Êý¾ÝÓò£¬´æ´¢Êý¾Ý};
SIMPLEQ_HEAD(head, items_type) list_head;
void List_Init(void)
{
SIMPLEQ_INIT(&list_head);
}
struct items_type node0 = {.value = 0};
struct items_type node1 = {.value = 1};
struct items_type node2 = {.value = 2};
struct items_type node3 = {.value = 3};
void List_Insert(void)
{
if (SIMPLEQ_EMPTY(&list_head)) {
SIMPLEQ_INSERT_HEAD(&list_head, &node0, field);
SIMPLEQ_INSERT_HEAD(&list_head, &node1, field);
SIMPLEQ_INSERT_HEAD(&list_head, &node2, field);
SIMPLEQ_INSERT_AFTER(&list_head, &node2, &node3, field);
/*2310*/
} else {
SIMPLEQ_INSERT_TAIL(&list_head, &node0, field);
SIMPLEQ_INSERT_TAIL(&list_head, &node1, field);
SIMPLEQ_INSERT_TAIL(&list_head, &node2, field);
}
}
#if 0
void List_Travel(void)
{
struct items_type * ptype = NULL;
do {
ptype = SIMPLEQ_FIRST(&list_head);
if (ptype == NULL) {
break;
} else {
printf("%d\r\n", ptype->value);
//ÒƳýµÚÒ»¸ö½áµã
SIMPLEQ_REMOVE_HEAD(&list_head, field);
}
}while(ptype != NULL);
}
#else
void List_Travel(void)
{
struct items_type *ptype;
SIMPLEQ_FOREACH(ptype, &list_head, field) {
printf("value = %4d,", ptype->value);
}
printf("\r\n");
}
#endif
void ListItems_Remove(void)
{
SIMPLEQ_REMOVE(&list_head, &node1, items_type, field);
}
void ListFirst(void)
{
struct items_type *type;
type = SIMPLEQ_FIRST(&list_head);
printf("%4d\r\n", type->value);
}
void SimpleQueue_Test(void)
{
List_Init();
List_Insert();
List_Travel();
ListItems_Remove();
List_Travel();
ListFirst();
while(1) {
}
}