雙向鍊錶C語言實現

2021-05-25 05:12:29 字數 3480 閱讀 1104

#ifndef __stdlist_h__

#define __stdlist_h__

typedef struct tagstdnode       stdnode, *lpstdnode;

typedef struct tagstdlist       stdlist, *lpstdlist;

// 鍊錶資料結構

struct tagstdnode ;

// 鍊錶節點結構

struct tagstdlist ;

// 用於鍊錶擴充套件的巨集

#define node_initializer    ((stdnode))

#define list_initializer    ((stdlist))

#define declarelistnode()  stdnode __snstdnode

#define init_listnode()     __snstdnode = node_initializer

// 初始化鍊錶

static inline

lpstdlist       twinapi     stdlistinit(

lpstdlist lplist

) // 獲取鍊錶頭部節點

static inline

lpstdnode       twinapi     stdlistgetheadnode(

lpstdlist lplist

) // 獲取鍊錶尾部節點

static inline

lpstdnode       twinapi     stdlistgettailnode(

lpstdlist lplist

) // 獲取給定節點的下乙個節點

static inline

lpstdnode       twinapi     stdlistgetnextnode(

lpstdnode lpnode

) // 獲取給定節點的上乙個節點

static inline

lpstdnode       twinapi     stdlistgetprevnode(

lpstdnode lpnode

) // 在鍊錶頭部插入乙個節點

static inline

void            twinapi     stdlistpushfront(

lpstdlist lplist,

lpstdnode lpnode

) // 在鍊錶尾部插入乙個節點

static inline

void            twinapi     stdlistpushback(

lpstdlist lplist,

lpstdnode lpnode

) // 在指定節點後插入乙個節點

static inline

void            twinapi     stdlistinsert(

lpstdlist lplist,

lpstdnode lpafter,

lpstdnode lpnode

) else

} // 從鍊錶頭部彈出乙個節點

static inline

lpstdnode       twinapi     stdlistpopfront(

lpstdlist lplist

) else

} // 從鍊錶尾部彈出乙個節點

static inline

lpstdnode       twinapi     stdlistpopback(

lpstdlist lplist

) else

} // 從鍊錶中刪除給定節點

static inline

lpstdnode       twinapi     stdlistremove(

lpstdlist lplist,

lpstdnode lpnode

) // 檢查鍊錶是否為空

static inline

bool            twinapi     stdlistisempty(

lpstdlist lplist

) // 獲取鍊錶中的節點數

static inline

long            twinapi     stdlistgetsize(

lpstdlist lplist

) return lnsize;

} // 合併兩個鍊錶

static inline

lpstdlist       twinapi     stdlistcombine(

lpstdlist lplist1,

lpstdlist lplist2

) else

lplist2->lphead = lplist2->lptail   = null;

} return lplist1;

} #endif//__stdlist_h__

演算法本身沒有什麼特別的地方,為什麼說這是乙個通用雙向鍊錶呢?奧妙就在那四個用於擴充套件的巨集。利用這幾個巨集你可以將這個雙向鍊錶擴充套件到任意結構。

例如,我們要實現乙個訊息佇列,那麼我們可以這樣定義訊息節點:

typedef struct tagmsgnode msgnode, *lpmsgnode;

而訊息佇列則可以直接用listnode結構來表示:

stdlist     lstmsgqueue;

這樣我們就可以用剛剛定義的函式來對這個訊息佇列進行操作了:

// 向訊息佇列插入乙個訊息

lpmsgnode lpmsgnode = memalloc(sizeof(msgnode));

lpmsgnode->init_listnode();

lpmsgnode->hwnd     = hwnd;

lpmsgnode->umsg     = wm_paint;

lpmsgnode->wparam   = null;

lpmsgnode->lparam   = null;

stdlistpushback(&lstmsgqueue, (lpstdnode)lpmsgnode);

// 從訊息佇列取出乙個訊息

lpmsgnode lpmsgnode = (lpmsgnode)stdlistpopfront(&lstmsgqueue);

// 刪除所有屬於hwnd的訊息

lpmsgnode lptemp    = (lpmsgnode)stdlistgetheadnode(&lstmsgqueue);

while(lptemp)

lptemp  = lpnext;

}

c語言實現雙向鍊錶

單向鍊錶有一定的缺陷,其中乙個就是只能一條路走到黑,只能前進不能後退,但雙向鍊錶就解決了這一問題 include include typedef struct node node,linklist void create list tail linklist l 頭插法建立 void create ...

C語言實現雙向鍊錶

1.定義兩個結構體,乙個表示鍊錶的乙個單元,另乙個表示鍊錶的頭結點 2.鍊錶的初始化 必須讓頭結點的next和prev指向自己 清除 不刪除頭結點 銷毀 刪除頭結點 3.增操作 每次增加需要開闢乙個單元,所以直接建立乙個函式用來建立單元 頭插 尾插 pos結點之前插 4.刪操作 分為三種 刪除pos...

C語言實現雙向鍊錶

linklist.h ifndef linklist h define linklist h 節點 包含前置指標和後置指標 struct listnode struct list define listnextnode x x x next null define listhead x x x he...