双向链表C语言实现

#ifndef __STDLIST_H__
#define __STDLIST_H__

typedef struct tagSTDNODE       STDNODE, *LPSTDNODE;
typedef struct tagSTDLIST       STDLIST, *LPSTDLIST;

// 链表数据结构
struct tagSTDNODE {
    LPSTDNODE           lpPrev;
    LPSTDNODE           lpNext;
};

// 链表节点结构
struct tagSTDLIST {
    LPSTDNODE           lpHead;
    LPSTDNODE           lpTail;
};

// 用于链表扩展的宏
#define NODE_INITIALIZER    ((STDNODE){ .lpPrev = NULL, .lpNext = NULL, })
#define LIST_INITIALIZER    ((STDLIST){ .lpHead = NULL, .lpTail = NULL, })
#define DECLARELISTNODE()  STDNODE __snStdNode
#define INIT_LISTNODE()     __snStdNode = NODE_INITIALIZER

// 初始化链表
STATIC INLINE
LPSTDLIST       TWINAPI     StdListInit(
                            LPSTDLIST lpList
                            ) {
    lpList->lpHead  = NULL;
    lpList->lpTail  = NULL;
    return lpList;
}

// 获取链表头部节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListGetHeadNode(
                            LPSTDLIST lpList
                            ) {
    return lpList->lpHead;
}

// 获取链表尾部节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListGetTailNode(
                            LPSTDLIST lpList
                            ) {
    return lpList->lpTail;
}

// 获取给定节点的下一个节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListGetNextNode(
                            LPSTDNODE lpNode
                            ) {
    return lpNode->lpNext;
}

// 获取给定节点的上一个节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListGetPrevNode(
                            LPSTDNODE lpNode
                            ) {
    return lpNode->lpPrev;
}

// 在链表头部插入一个节点
STATIC INLINE
VOID            TWINAPI     StdListPushFront(
                            LPSTDLIST lpList,
                            LPSTDNODE lpNode
                            ) {
    lpNode->lpPrev  = NULL;
    lpNode->lpNext  = lpList->lpHead;
    if(lpList->lpHead)
        lpList->lpHead->lpPrev  = lpNode;
    else
        lpList->lpTail  = lpNode;
    lpList->lpHead  = lpNode;
}

// 在链表尾部插入一个节点
STATIC INLINE
VOID            TWINAPI     StdListPushBack(
                            LPSTDLIST lpList,
                            LPSTDNODE lpNode
                            ) {
    lpNode->lpNext  = NULL;
    lpNode->lpPrev  = lpList->lpTail;
    if(lpList->lpTail)
        lpList->lpTail->lpNext  = lpNode;
    else
        lpList->lpHead  = lpNode;
    lpList->lpTail  = lpNode;
}

// 在指定节点后插入一个节点
STATIC INLINE
VOID            TWINAPI     StdListInsert(
                            LPSTDLIST lpList,
                            LPSTDNODE lpAfter,
                            LPSTDNODE lpNode
                            ) {
    if(lpAfter) {
        if(lpAfter->lpNext)
            lpAfter->lpNext->lpPrev = lpNode;
        else
            lpList->lpTail  = lpNode;
        lpNode->lpPrev  = lpAfter;
        lpNode->lpNext  = lpAfter->lpNext;
        lpAfter->lpNext = lpNode;
    } else {
        StdListPushFront(lpList, lpNode);
    }
}

// 从链表头部弹出一个节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListPopFront(
                            LPSTDLIST lpList
                            ) {
    if(lpList->lpHead) {
        LPSTDNODE lpNode    = lpList->lpHead;
        if(lpList->lpHead->lpNext)
            lpList->lpHead->lpNext->lpPrev  = NULL;
        else
            lpList->lpTail  = NULL;
        lpList->lpHead  = lpList->lpHead->lpNext;
        lpNode->lpPrev  = lpNode->lpNext    = NULL;
        return lpNode;
    } else {
        return NULL;
    }
}

// 从链表尾部弹出一个节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListPopBack(
                            LPSTDLIST lpList
                            ) {
    if(lpList->lpTail) {
        LPSTDNODE lpNode    = lpList->lpTail;
        if(lpList->lpTail->lpPrev)
            lpList->lpTail->lpPrev->lpNext  = NULL;
        else
            lpList->lpHead  = NULL;
        lpList->lpTail  = lpList->lpTail->lpPrev;
        lpNode->lpPrev  = lpNode->lpNext    = NULL;
        return lpNode;
    } else {
        return NULL;
    }
}

// 从链表中删除给定节点
STATIC INLINE
LPSTDNODE       TWINAPI     StdListRemove(
                            LPSTDLIST lpList,
                            LPSTDNODE lpNode
                            ) {
    if(lpNode->lpPrev)
        lpNode->lpPrev->lpNext  = lpNode->lpNext;
    else
        lpList->lpHead  = lpNode->lpNext;
    if(lpNode->lpNext)
        lpNode->lpNext->lpPrev  = lpNode->lpPrev;
    else
        lpList->lpTail  = lpNode->lpPrev;
    return lpNode;
}

// 检查链表是否为空
STATIC INLINE
BOOL            TWINAPI     StdListIsEmpty(
                            LPSTDLIST lpList
                            ) {
    if(lpList->lpHead || lpList->lpTail)
        return FALSE;
    else
        return TRUE;
}

// 获取链表中的节点数
STATIC INLINE
LONG            TWINAPI     StdListGetSize(
                            LPSTDLIST lpList
                            ) {
    LONG lnSize = 0;
    LPSTDNODE lpNode    = StdListGetHeadNode(lpList);
    while(lpNode) {
        ++ lnSize;
        lpNode  = StdListGetNextNode(lpNode);
    }
    return lnSize;
}

// 合并两个链表
STATIC INLINE
LPSTDLIST       TWINAPI     StdListCombine(
                            LPSTDLIST lpList1,
                            LPSTDLIST lpList2
                            ) {
    if(!StdListIsEmpty(lpList2)) {
        if(!StdListIsEmpty(lpList1)) {
            lpList1->lpTail->lpNext = lpList2->lpHead;
            lpList2->lpHead->lpPrev = lpList1->lpTail;
            lpList1->lpTail = lpList2->lpTail;
        } else {
            lpList1->lpHead = lpList2->lpHead;
            lpList1->lpTail = lpList2->lpTail;
        }
        lpList2->lpHead = lpList2->lpTail   = NULL;
    }
    return lpList1;
}

#endif//__STDLIST_H__

算法本身没有什么特别的地方,为什么说这是一个通用双向链表呢?奥妙就在那四个用于扩展的宏。利用这几个宏你可以将这个双向链表扩展到任意结构。

例如,我们要实现一个消息队列,那么我们可以这样定义消息节点:

typedef struct tagMSGNODE {
    DECLARELISTNODE();
    HWND        hWnd;
    UINT        uMsg;
    WPARAM      wParam;
    LPARAM      lParam;
} 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) {
    LPMSGNODE lpNext    = (LPMSGNODE)StdListGetNextNode(&lstMsgQueue, (LPSTDNODE)lpTemp);
    if(lpTemp->hWnd == hWnd) {
        StdListRemove(&lstMsgQueue, (LPSTDNODE)lpTemp);
                MemFree(lpTemp);
        }
    lpTemp  = lpNext;
}


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/EricLogic/archive/2009/01/10/3747590.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值