双链表操作
来源:互联网 发布:淘宝交不了保证金 编辑:程序博客网 时间:2024/06/09 16:38
dlist.h:
#ifndef DLIST_H#define DLIST_Htypedef int Item;struct dnode { Item item; struct dnode *prev; struct dnode *next;};typedef struct dnode* dlist;void DListAddItem(dlist *plist, Item item);struct dnode* DListSearchItem(dlist *plist, Item item);void DListDelItem(dlist *plist, Item item);#endif
dlist.cpp:
#include "stdafx.h"#include "dlist.h"#include <assert.h>#include <stdlib.h>static inline void CopyItem (Item item, struct dnode *pnode){ pnode->item = item;}static inline int ItempCmp(Item item1, Item item2){ return item1 > item2 ? 1 : (item1 == item2 ? 0 : -1);}/********************************************** 添加元素到链表尾部 **********************************************/void DListAddItem(dlist *plist, Item item){ assert(NULL != plist); struct dnode* pnew = (struct dnode *)malloc(sizeof(struct dnode)); assert(NULL != plist); CopyItem(item, pnew); pnew->next = NULL; pnew->prev = NULL; struct dnode* pscan = *plist; if (NULL == pscan) // 空链表 { pnew->next = pnew; pnew->prev = pnew; *plist = pnew; } else { pnew->prev = pscan->prev; pnew->next = pscan; pscan->prev->next = pnew; pscan->prev = pnew; }} /********************************************** 搜索元素 链表中存在元素,则返回第一个匹配元素的节点 若不存在或者链表为空,则返回空指针 **********************************************/ struct dnode* DListSearchItem(dlist *plist,Item item) { assert(NULL != plist); struct dnode *pscan = *plist; if (NULL == pscan) return (struct dnode*)0; do { if (0 == ItempCmp(item, pscan->item)) return pscan; pscan = pscan->next; }while(pscan != *plist); return (struct dnode*)0;} /********************************************** 删除元素 **********************************************/ void DListDelItem(dlist *plist, Item item) { struct dnode *pdel; pdel = DListSearchItem(plist, item); if (NULL != pdel) { pdel->prev->next = pdel->next; pdel->next->prev = pdel->prev; if (*plist == pdel) // 删除头结点 { *plist = pdel->next; if (*plist == pdel) // 链表只有1个节点 { *plist = NULL; } } free(pdel); }} /*************************************************************************linux中的双链表实现:此实现方案最大的好处是不需要Item每变换一次就重新定义一次节点**************************************************************************/// 双链表---begin /********************************************************** TYPE: 结构体类型名 MEMBER: 结构体成员名 **********************************************************/ #define offsetof(TYPE, MEMBER) (((TYPE *)0)->MEMBER) /********************************************************** ptr: 结构体成员指针 type: 结构体类型名 member: ptr对应的结构体成员名 **********************************************************/ #define container_of(ptr, type, member) \ (type*)((char *)ptr - offsetof(type, member)) struct list { struct list *prev, *next; };#define LIST_HEAD_INIT(name) {&(name), &(name)} #define LIST_HEAD(name) \ struct list name = LIST_HEAD_INIT(name) static inline void list_init(struct list *list) { list->next = list; list->prev = list; } static inline int list_empty(struct list *list) { return list->next == list; } // 将new_link插入到link之前 static inline void list_insert(struct list *link, struct list *new_link) { new_link->prev = link->prev; new_link->next = link; new_link->prev->next = new_link; new_link->next->prev = new_link; } static inline void list_append(struct list *list, struct list *new_link) { list_insert(list, new_link); } static inline void list_remove(struct list *link) { link->prev->next = link->next; link->next->prev = link->prev; } /********************************************************** 获取link节点对应的结构体变量地址 link: 链表节点指针 type: 结构体类型名 member: 结构体成员变量名 **********************************************************/ #define list_entry(link, type, member) \ ((type *)((char *)(link)-(unsigned long)(&((type *)0)->member))) /********************************************************** 获取链表头节点对应的结构体变量地址 list: 链表头指针 type: 结构体类型名 member: 结构体成员变量名 Note: 链表头节点实际为链表头的下一个节点,链表头未使用,相当于哨兵 **********************************************************/ #define list_head(list, type, member) \ list_entry((list)->next, type, member) /********************************************************** 获取链表尾节点对应的结构体变量地址 list: 链表头指针 type: 结构体类型名 member: 结构体成员变量名 **********************************************************/ #define list_tail(list, type, member) \ list_entry((list)->prev, type, member) /********************************************************** 返回链表下一个节点对应的结构体指针 elm: 结构体变量指针 type: 结构体类型名 member: 结构体成员变量名(链表变量名) **********************************************************/ #define list_next(elm,type,member) \ list_entry((elm)->member.next, type, member) /********************************************************** 遍历链表所有节点对应的结构体 pos: 结构体指针 type: 结构体类型名 list: 链表头指针 member: 结构体成员变量名(链表变量名) Note: 链表头未使用,因此遍历结束后,pos指向的不是有效的结构体地址 **********************************************************/ #define list_for_each_entry(pos, type, list, member) \ for (pos = list_head(list, type, member); \ &pos->member != (list); \ pos = list_next(pos, type, member))
0 0
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表操作
- 双链表基本操作
- 双链表基本操作
- 双链表操作实例
- 双链表相关操作
- 双链表基本操作
- 双链表的相关操作
- 双链表基本操作
- 双链表基本操作。
- 双链表的基本操作
- 双链表操作,图解
- C/C++ 笔试、面试题目汇总1——代码相关
- 引用相关知识总结
- extern “C”用法详解
- 基本排序算法
- 单链表操作
- 双链表操作
- POJ 2391 Ombrophobic Bovines (二分 + floyd + 网络流)
- Log4Net的坎坷配置之旅。
- android 要学会哪些
- 移动App架构设计
- 回溯算法 (转)
- OpenCV基础篇之读取显示图片
- In-depth analysis of Oracle memory
- 虚拟机ubuntu下挂载windows下的硬盘