目录
一、链表
1、单向链表
2、单向循环链表
3、双向链表
4、双向循环链表
二、链表优势
1、使用堆内存,内存空间不要求连续,内存利用率高
2、增删方便
三、单向链表
1、结构体设计
设计头结点、普通节点(或者说链表节点)。
头结点:可以存储链表节点之外的数据,比如节点个数。设计头结点可以使得编程容易扩展以及方便操作
普通节点:数据域与指针域。由于是单向链表,指针域只需要一个 next 指向下一个节点即可(最后一个节点的 next 指针指向 NULL)。
/* 数据结构设计 */
typedef struct SIGLE_LINK_NODE
{
struct SIGLE_LINK_NODE *next; // 指针域
Data data; // 数据域
}SigleLinkNode; // 普通节点
typedef struct
{
SigleLinkNode *next;
int numNode;
}SigleHeadNode; // 头节点
宏定义:
/* 宏定义 */
#define RET_INT_SUCC (0)
#define RET_INT_FAIL (-1)
#define RET_BOOL_SUCC true
#define RET_BOOL_FAIL false
#define PR_ERR(fmt, arg...) fprintf(stderr, "\r\033[K\033[31m[%s][%d]:"fmt"\033[0m\n", __func__, __LINE__, ##arg)
#define PR_INFO(fmt, arg...) fprintf(stderr, "\r\033[K\033[33m"fmt"\033[0m\n", ##arg)
#define PR_RESULT_SUCC(fmt, arg...) fprintf(stderr, "\r\033[K\033[32m"fmt"\033[0m\n", ##arg)
#define PR_RESULT_FAIL(fmt, arg...) fprintf(stderr, "\r\033[K\033[31m"fmt"\033[0m\n", ##arg)
#define CL_SCREEN() clear_screen()
2、接口设计
// 函数声明
// 1、初始化, 创建头节点
SigleHeadNode *initSigleLinkList();
// 2、创建普通节点
static SigleLinkNode *createNode(int id, int score);
// 3、判断是否为空链表
static bool isEmptyLinkList(SigleHeadNode* head);
// 4、添加一个新节点
// 尾插
static bool tailAddNode(SigleHeadNode *head, SigleLinkNode *newNode);
// 头插
static bool headAddNode(SigleHeadNode *head, SigleLinkNode *newNode);
// 5、查询一个节点,根据id来查询
static SigleLinkNode *queryNode(SigleHeadNode *head, int id);
// 6、删除一个节点,根据id来删除
static bool delNode(SigleHeadNode *head, int id);
// 7、打印链表
static void dumpLinkList(SigleHeadNode *head);
// 8、销毁链表
static bool destroyLinkList(SigleHeadNode *head);
3、接口实现
/* ***** 单向链表: 内部接口设计 START ***** */
// 1、初始化, 创建头节点
SigleHeadNode *initSigleLinkList()
{
SigleHeadNode *head = calloc(1, sizeof(SigleHeadNode));
if(NULL == head)
{
PR_ERR("calloc fail");
return head;
}
head->numNode = 0;
head->next = NULL;
return head;
}
// 2、创建普通节点
static SigleLinkNode *createNode(int id, int score)
{
SigleLinkNode *node = calloc(1, sizeof(SigleLinkNode));
if(NULL == node)
{
PR_ERR("calloc fail");
return node;
}
node->data.id = id;
node->data.score = score;
node->next = NULL;
return node;
}
// 3、判断是否为空链表
static bool isEmptyLinkList(SigleHeadNode* head)
{
if(NULL == head)
return RET_BOOL_FAIL;
if(0 == head->numNode)
return RET_BOOL_SUCC;
return RET_BOOL_FAIL;
}
// 4、添加一个新节点
// 尾插
static bool tailAddNode(SigleHeadNode *head, SigleLinkNode *newNode)
{
SigleLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
head->next = newNode;
head->numNode ++;
return RET_BOOL_SUCC;
}
node = head->next;
while(NULL != node && NULL != node->next)
node = node->next;
node->next = newNode;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 头插
static bool headAddNode(SigleHeadNode *head, SigleLinkNode *newNode)
{
SigleLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
node = head->next;
head->next = newNode;
newNode->next = node;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 5、查询一个节点,根据id来查询
static SigleLinkNode *queryNode(SigleHeadNode *head, int id)
{
SigleLinkNode *node = NULL;
if(NULL == head)
return NULL;
if(isEmptyLinkList(head))
return NULL;
node = head->next;
while(NULL != node)
{
if(node->data.id == id)
return node;
node = node->next;
}
return NULL;
}
// 6、删除一个节点,根据id来删除
static bool delNode(SigleHeadNode *head, int id)
{
SigleLinkNode *preNode = NULL;
SigleLinkNode *node = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
return RET_BOOL_FAIL;
node = head->next;
while(NULL != node)
{
if(node->data.id == id)
break;
preNode = node;
node = node->next;
}
// not found
if(NULL == node)
return RET_BOOL_FAIL;
// 如果要删掉的是首个节点
if(id == head->next->data.id)
head->next = node->next;
else
preNode->next = node->next;
free(node);
head->numNode --;
return RET_BOOL_SUCC;
}
// 7、打印链表
static void dumpLinkList(SigleHeadNode *head)
{
int i = 0;
SigleLinkNode *node = NULL;
if(NULL == head)
return ;
PR_INFO("numNode: %d", head->numNode);
if(isEmptyLinkList(head))
return ;
node = head->next;
while(NULL != node)
{
PR_INFO("number(%d): id(%d) score(%d)", ++i, node->data.id, node->data.score);
node = node->next;
}
}
// 8、销毁链表
static bool destroyLinkList(SigleHeadNode *head)
{
SigleLinkNode *node = NULL;
SigleLinkNode *nextNode = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
free(head);
return RET_BOOL_SUCC;
}
node = head->next;
while(NULL != node)
{
nextNode = node->next;
free(node);
node = nextNode;
}
free(head);
return RET_BOOL_SUCC;
}
/* ***** 单向链表: 内部接口设计 END ***** */
四、单向循环链表
1、结构体设计
结构体设计跟单向链表一致,区别在于单向循环链表的最后一个节点的 next 指针指向 head 头结点。整体上链表形成一个“环”。
/* 注:单向链表 && 单向循环链表
* 区别在于:
* 单向链表的末尾next指针指向 NULL
* 单向循环链表的末尾next指针指向 head
*/
/* 数据结构设计 */
typedef struct SIGLE_CIRCULAR_LINK_NODE
{
struct SIGLE_CIRCULAR_LINK_NODE *next; // 指针域
Data data; // 数据域
}SigleCircularLinkNode; // 普通节点
typedef struct
{
struct SIGLE_CIRCULAR_LINK_NODE *next;
int numNode;
}SigleCircularHeadNode; // 头节点
#define TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head) (SigleCircularLinkNode *)head
/* *
* 把指针域放在首个结构体成员,目的是作强制类型转换.
* 如下:
* SigleCircularHeadNode *head = calloc(1, sizeof(SigleCircularHeadNode));
*
* head->next = TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head); // like when initSigleCircularLinkList
*/
2、接口设计
// 函数声明
// 1、初始化, 创建头节点
SigleCircularHeadNode *initSigleCircularLinkList();
// 2、创建普通节点
static SigleCircularLinkNode *createNode(int id, int score);
// 3、判断是否为空链表
static bool isEmptyLinkList(SigleCircularHeadNode* head);
// 4、添加一个新节点
// 尾插
static bool tailAddNode(SigleCircularHeadNode *head, SigleCircularLinkNode *newNode);
// 头插
static bool headAddNode(SigleCircularHeadNode *head, SigleCircularLinkNode *newNode);
// 5、查询一个节点,根据id来查询
static SigleCircularLinkNode *queryNode(SigleCircularHeadNode *head, int id);
// 6、删除一个节点,根据id来删除
static bool delNode(SigleCircularHeadNode *head, int id);
// 7、打印链表
static void dumpLinkList(SigleCircularHeadNode *head);
// 8、销毁链表
static bool destroyLinkList(SigleCircularHeadNode *head);
3、接口实现
/* ***** 单向循环链表: 内部接口设计 START ***** */
// 1、初始化, 创建头节点
SigleCircularHeadNode *initSigleCircularLinkList()
{
SigleCircularHeadNode *head = calloc(1, sizeof(SigleCircularHeadNode));
if(NULL == head)
{
PR_ERR("calloc fail");
return head;
}
head->numNode = 0;
head->next = TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head);
return head;
}
// 2、创建普通节点
static SigleCircularLinkNode *createNode(int id, int score)
{
SigleCircularLinkNode *node = calloc(1, sizeof(SigleCircularLinkNode));
if(NULL == node)
{
PR_ERR("calloc fail");
return node;
}
node->data.id = id;
node->data.score = score;
node->next = NULL;
return node;
}
// 3、判断是否为空链表
static bool isEmptyLinkList(SigleCircularHeadNode* head)
{
if(NULL == head)
return RET_BOOL_FAIL;
if(0 == head->numNode)
return RET_BOOL_SUCC;
return RET_BOOL_FAIL;
}
// 4、添加一个新节点
// 尾插
static bool tailAddNode(SigleCircularHeadNode *head, SigleCircularLinkNode *newNode)
{
SigleCircularLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
head->next = newNode;
newNode->next = TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head);
head->numNode ++;
return RET_BOOL_SUCC;
}
node = head->next;
while( node->next != TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head) )
node = node->next;
node->next = newNode;
newNode->next = TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head);
head->numNode ++;
return RET_BOOL_SUCC;
}
// 头插
static bool headAddNode(SigleCircularHeadNode *head, SigleCircularLinkNode *newNode)
{
SigleCircularLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
node = head->next;
head->next = newNode;
newNode->next = node;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 5、查询一个节点,根据id来查询
static SigleCircularLinkNode *queryNode(SigleCircularHeadNode *head, int id)
{
SigleCircularLinkNode *node = NULL;
if(NULL == head)
return NULL;
if(isEmptyLinkList(head))
return NULL;
node = head->next;
while(node != TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head))
{
if(node->data.id == id)
return node;
node = node->next;
}
return NULL;
}
// 6、删除一个节点,根据id来删除
static bool delNode(SigleCircularHeadNode *head, int id)
{
SigleCircularLinkNode *preNode = NULL;
SigleCircularLinkNode *node = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
return RET_BOOL_FAIL;
node = head->next;
while(node != TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head))
{
if(node->data.id == id)
break;
preNode = node;
node = node->next;
}
// not found
if(node == TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head))
return RET_BOOL_FAIL;
// 如果要删掉的是首个节点
if(id == head->next->data.id)
head->next = node->next;
else
preNode->next = node->next;
free(node);
head->numNode --;
return RET_BOOL_SUCC;
}
// 7、打印链表
static void dumpLinkList(SigleCircularHeadNode *head)
{
int i = 0;
SigleCircularLinkNode *node = NULL;
if(NULL == head)
return ;
PR_INFO("numNode: %d", head->numNode);
if(isEmptyLinkList(head))
return ;
node = head->next;
while(node != TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head))
{
PR_INFO("number(%d): id(%d) score(%d)", ++i, node->data.id, node->data.score);
node = node->next;
}
}
// 8、销毁链表
static bool destroyLinkList(SigleCircularHeadNode *head)
{
SigleCircularLinkNode *node = NULL;
SigleCircularLinkNode *nextNode = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
free(head);
return RET_BOOL_SUCC;
}
node = head->next;
while(node != TO_SIGLE_CIRCULAR_LINKNODE_TYPE(head))
{
nextNode = node->next;
free(node);
node = nextNode;
}
free(head);
return RET_BOOL_SUCC;
}
/* ***** 单向循环链表: 内部接口设计 END ***** */
五、双向链表
1、结构体设计
双向链表跟单向链表相比较,双向链表的链表节点的指针域多了一个 prev 节点,用于指向前一个节点。但对于 head 节点来说,head 的 prev 节点指向 NULL。
/* 注:单向链表 && 双向链表
* 区别在于:
* 单向链表的只有一个next指针指向下一个节点
* 双向链表的存在prev指针指向前一个节点与next指针指向下一个节点
*/
/* 数据结构设计 */
typedef struct DOUBLY_LINK_NODE
{
struct DOUBLY_LINK_NODE *prev; // 指针域: 前驱指针
struct DOUBLY_LINK_NODE *next; // 指针域: 后驱指针
Data data; // 数据域
}DoublyLinkNode; // 普通节点
typedef struct
{
DoublyLinkNode *prev;
DoublyLinkNode *next;
int numNode;
}DoublyHeadNode; // 头节点
#define TO_DOUBLY_LINKNODE_TYPE(head) (DoublyLinkNode *)head
2、接口设计
// 函数声明
// 1、初始化, 创建头节点
DoublyHeadNode *initDoublyLinkList();
// 2、创建普通节点
static DoublyLinkNode *createNode(int id, int score);
// 3、判断是否为空链表
static bool isEmptyLinkList(DoublyHeadNode* head);
// 4、添加一个新节点
// 尾插
static bool tailAddNode(DoublyHeadNode *head, DoublyLinkNode *newNode);
// 头插
static bool headAddNode(DoublyHeadNode *head, DoublyLinkNode *newNode);
// 5、查询一个节点,根据id来查询
static DoublyLinkNode *queryNode(DoublyHeadNode *head, int id);
// 6、删除一个节点,根据id来删除
static bool delNode(DoublyHeadNode *head, int id);
// 7、打印链表
static void dumpLinkList(DoublyHeadNode *head);
// 8、销毁链表
static bool destroyLinkList(DoublyHeadNode *head);
3、接口实现
/* ***** 双向链表: 内部接口设计 START ***** */
// 1、初始化, 创建头节点
DoublyHeadNode *initDoublyLinkList()
{
DoublyHeadNode *head = calloc(1, sizeof(DoublyHeadNode));
if(NULL == head)
{
PR_ERR("calloc fail");
return head;
}
head->numNode = 0;
head->prev = NULL;
head->next = NULL;
return head;
}
// 2、创建普通节点
static DoublyLinkNode *createNode(int id, int score)
{
DoublyLinkNode *node = calloc(1, sizeof(DoublyLinkNode));
if(NULL == node)
{
PR_ERR("calloc fail");
return node;
}
node->data.id = id;
node->data.score = score;
node->prev = NULL;
node->next = NULL;
return node;
}
// 3、判断是否为空链表
static bool isEmptyLinkList(DoublyHeadNode* head)
{
if(NULL == head)
return RET_BOOL_FAIL;
if(0 == head->numNode)
return RET_BOOL_SUCC;
return RET_BOOL_FAIL;
}
// 4、添加一个新节点
// 尾插
static bool tailAddNode(DoublyHeadNode *head, DoublyLinkNode *newNode)
{
DoublyLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
// head->prev = NULL;
head->next = newNode;
head->numNode ++;
return RET_BOOL_SUCC;
}
node = head->next;
while(NULL != node && NULL != node->next)
node = node->next;
node->next = newNode;
newNode->prev = node;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 头插
static bool headAddNode(DoublyHeadNode *head, DoublyLinkNode *newNode)
{
DoublyLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
node = head->next;
if(NULL == node) // 添加的是首个链表节点
{
head->next = newNode;
newNode->prev = TO_DOUBLY_LINKNODE_TYPE(head);
newNode->next = NULL;
}
else
{
head->next = newNode;
newNode->prev = TO_DOUBLY_LINKNODE_TYPE(head);
newNode->next = node;
node->prev = newNode;
}
head->numNode ++;
return RET_BOOL_SUCC;
}
// 5、查询一个节点,根据id来查询
static DoublyLinkNode *queryNode(DoublyHeadNode *head, int id)
{
DoublyLinkNode *node = NULL;
if(NULL == head)
return NULL;
if(isEmptyLinkList(head))
return NULL;
node = head->next;
while(NULL != node)
{
if(node->data.id == id)
return node;
node = node->next;
}
return NULL;
}
// 6、删除一个节点,根据id来删除
static bool delNode(DoublyHeadNode *head, int id)
{
DoublyLinkNode *preNode = NULL;
DoublyLinkNode *node = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
return RET_BOOL_FAIL;
node = head->next;
while(NULL != node)
{
if(node->data.id == id)
break;
preNode = node;
node = node->next;
}
// not found
if(NULL == node)
return RET_BOOL_FAIL;
// 最后一个
if(NULL == node->next)
{
node->prev->next = NULL;
}
else
{
node->prev->next = node->next;
node->next->prev = node->prev;
}
free(node);
head->numNode --;
return RET_BOOL_SUCC;
}
// 7、打印链表
static void dumpLinkList(DoublyHeadNode *head)
{
int i = 0;
DoublyLinkNode *node = NULL;
if(NULL == head)
return ;
PR_INFO("numNode: %d", head->numNode);
if(isEmptyLinkList(head))
return ;
node = head->next;
while(NULL != node)
{
PR_INFO("number(%d): id(%d) score(%d)", ++i, node->data.id, node->data.score);
node = node->next;
}
}
// 8、销毁链表
static bool destroyLinkList(DoublyHeadNode *head)
{
DoublyLinkNode *node = NULL;
DoublyLinkNode *nextNode = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
free(head);
return RET_BOOL_SUCC;
}
node = head->next;
while(NULL != node)
{
nextNode = node->next;
free(node);
node = nextNode;
}
free(head);
return RET_BOOL_SUCC;
}
/* ***** 双向链表: 内部接口设计 END ***** */
六、双向循环链表
1、结构体设计
/* 注:双向链表 && 双向循环链表
* 区别在于:
* 双向链表的head节点的prev指向NULL, 最后一个节点的next指向NULL
* 双向循环链表的head节点的prev指向最后一个节点, 最后一个节点的next指向head
*/
/* 数据结构设计 */
typedef struct DOUBLY_CIRCULAR_LINK_NODE
{
struct DOUBLY_CIRCULAR_LINK_NODE *prev; // 指针域: 前驱指针
struct DOUBLY_CIRCULAR_LINK_NODE *next; // 指针域: 后驱指针
Data data; // 数据域
}DoublyCircularLinkNode; // 普通节点
typedef struct
{
DoublyCircularLinkNode *prev;
DoublyCircularLinkNode *next;
int numNode;
}DoublyCircularHeadNode; // 头节点
#define TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head) (DoublyCircularLinkNode *)head
2、接口设计
// 函数声明
// 1、初始化, 创建头节点
DoublyCircularHeadNode *initDoublyLinkList();
// 2、创建普通节点
static DoublyCircularLinkNode *createNode(int id, int score);
// 3、判断是否为空链表
static bool isEmptyLinkList(DoublyCircularHeadNode* head);
// 4、添加一个新节点
// 尾插
static bool tailAddNode(DoublyCircularHeadNode *head, DoublyCircularLinkNode *newNode);
// 头插
static bool headAddNode(DoublyCircularHeadNode *head, DoublyCircularLinkNode *newNode);
// 5、查询一个节点,根据id来查询
static DoublyCircularLinkNode *queryNode(DoublyCircularHeadNode *head, int id);
// 6、删除一个节点,根据id来删除
static bool delNode(DoublyCircularHeadNode *head, int id);
// 7、打印链表
static void dumpLinkList(DoublyCircularHeadNode *head);
// 8、销毁链表
static bool destroyLinkList(DoublyCircularHeadNode *head);
3、接口实现
/* ***** 双向循环链表: 内部接口设计 START ***** */
// 1、初始化, 创建头节点
DoublyCircularHeadNode *initDoublyCircularLinkList()
{
DoublyCircularHeadNode *head = calloc(1, sizeof(DoublyCircularHeadNode));
if(NULL == head)
{
PR_ERR("calloc fail");
return head;
}
head->numNode = 0;
head->prev = TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head);
head->next = TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head);
return head;
}
// 2、创建普通节点
static DoublyCircularLinkNode *createNode(int id, int score)
{
DoublyCircularLinkNode *node = calloc(1, sizeof(DoublyCircularLinkNode));
if(NULL == node)
{
PR_ERR("calloc fail");
return node;
}
node->data.id = id;
node->data.score = score;
node->prev = NULL;
node->next = NULL;
return node;
}
// 3、判断是否为空链表
static bool isEmptyLinkList(DoublyCircularHeadNode* head)
{
if(NULL == head)
return RET_BOOL_FAIL;
if(0 == head->numNode)
return RET_BOOL_SUCC;
return RET_BOOL_FAIL;
}
// 4、添加一个新节点
// 尾插
static bool tailAddNode(DoublyCircularHeadNode *head, DoublyCircularLinkNode *newNode)
{
DoublyCircularLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
head->prev = newNode;
head->next = newNode;
newNode->prev = TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head);
newNode->next = TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head);
head->numNode ++;
return RET_BOOL_SUCC;
}
node = head->next;
while(node->next != TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head))
node = node->next;
node->next->prev = newNode;
newNode->next = node->next;
newNode->prev = node;
node->next = newNode;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 头插
static bool headAddNode(DoublyCircularHeadNode *head, DoublyCircularLinkNode *newNode)
{
DoublyCircularLinkNode *node = NULL;
if(NULL == head || NULL == newNode)
return RET_BOOL_FAIL;
node = head->next;
head->next = newNode;
newNode->prev = TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head);
newNode->next = node;
node->prev = newNode;
head->numNode ++;
return RET_BOOL_SUCC;
}
// 5、查询一个节点,根据id来查询
static DoublyCircularLinkNode *queryNode(DoublyCircularHeadNode *head, int id)
{
DoublyCircularLinkNode *node = NULL;
if(NULL == head)
return NULL;
if(isEmptyLinkList(head))
return NULL;
node = head->next;
while( node != TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head) )
{
if(node->data.id == id)
return node;
node = node->next;
}
return NULL;
}
// 6、删除一个节点,根据id来删除
static bool delNode(DoublyCircularHeadNode *head, int id)
{
DoublyCircularLinkNode *node = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
return RET_BOOL_FAIL;
node = head->next;
while(node != TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head))
{
if(node->data.id == id)
break;
node = node->next;
}
// not found
if(node == TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head))
return RET_BOOL_FAIL;
node->prev->next = node->next;
node->next->prev = node->prev;
free(node);
head->numNode --;
return RET_BOOL_SUCC;
}
// 7、打印链表
static void dumpLinkList(DoublyCircularHeadNode *head)
{
int i = 0;
DoublyCircularLinkNode *node = NULL;
if(NULL == head)
return ;
PR_INFO("numNode: %d", head->numNode);
if(isEmptyLinkList(head))
return ;
node = head->next;
while(node != TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head))
{
PR_INFO("number(%d): id(%d) score(%d)", ++i, node->data.id, node->data.score);
node = node->next;
}
}
// 8、销毁链表
static bool destroyLinkList(DoublyCircularHeadNode *head)
{
DoublyCircularLinkNode *node = NULL;
DoublyCircularLinkNode *nextNode = NULL;
if(NULL == head)
return RET_BOOL_FAIL;
if(isEmptyLinkList(head))
{
free(head);
return RET_BOOL_SUCC;
}
node = head->next;
while(node != TO_DOUBLY_CIRCULAR_LINKNODE_TYPE(head))
{
nextNode = node->next;
// node->prev->next = node->next;
// node->next->prev = node->prev;
free(node);
node = nextNode;
}
free(head);
return RET_BOOL_SUCC;
}
/* ***** 双向循环链表: 内部接口设计 END ***** */
七、源码结构 && 测试
1、源码结构
### tree 命令查看
LINK_LIST/
├── include
│ ├── common.h
│ ├── doubly_circular_linklist.h
│ ├── doubly_linklist.h
│ ├── sigle_circular_linklist.h
│ └── sigle_linklist.h
└── src
├── common.c
├── doubly_circular_linklist.c
├── doubly_linklist.c
├── main.c
├── sigle_circular_linklist.c
└── sigle_linklist.c
2 directories, 11 files
源码下载:通过网盘分享的文件:link_list.zip
链接: https://pan.baidu.com/s/19DC1t6ICAuCM8etoS1mDOw 提取码: akmx
2、编译
LINK_LIST$ gcc src/*.c -I./include/ -o link_list
3、测试
1、请选择要选择测试的链表结构:
2、测试接口