链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。(百度百科)。
通俗来讲,链表的数据存储位置不确定,但是可以通过链表结构中的指针指向相应的数据,从而达到逻辑连续的目的。
链表适用于长度不确定的数据结构,插入或删除某个元素不需要调整整个数据结构。
链表不适用于频繁查找某个数据。
以下为源码,包含单链表,双链表和循环双链表
list.h
#ifndef __LIST_H__
#define __LIST_H__
#include "stm32f10x.h"
#include "stdlib.h"
#define MaxListLength 20
#define SingleList 1
#ifdef SingleList
#define SingleListMode (1)
typedef struct ListNode
{
uint32_t value;
struct ListNode *pNext;
}ListNode;
#endif
#ifdef DoubleList
#define DoubleListMode (1)
typedef struct ListNode
{
uint32_t value;
struct ListNode *pNext;
struct ListNode *pLast;
}ListNode;
#endif
#ifdef LoopList
#define LoopListMode (1)
typedef struct ListNode
{
uint32_t value;
struct ListNode *pNext;
struct ListNode *pLast;
}ListNode;
#endif
typedef unsigned int ListState;
uint32_t List_GetListNodeCnt(ListNode *pHead);
ListState List_Init(ListNode * pHead,const uint32_t value);
ListState List_InsertNode(ListNode *pHead,const uint32_t node ,const uint32_t value);
ListState List_DeleteNode(ListNode *pHead,const uint32_t node);
ListState List_DeleteVal (ListNode *pHead,const uint32_t value);
ListNode* List_GetValueList (ListNode *pHead,const uint32_t value);
#endif
以下为list.c
#include "list.h"
static ListNode ListResult = {0};
/**
* @name List_Init.
* @brief Creat a list head.
* @param ListNode * pHead: Head of the list.
uint32_t value: Value of the head.
* @retval 0 : Succeed.
1 : There is no stack of head.
* @author Jiao Wo Yi Sheng Xiao Ming Ge.
* @Date 2018.5.30.
**/
ListState List_Init(ListNode * pHead,const uint32_t value)
{
// pHead = (ListNode *)malloc(sizeof(ListNode));
if(pHead == NULL)
return 1;
#ifdef SingleListMode
pHead->pNext = NULL;
pHead->value = value;
#endif
#ifdef DoubleListMode
pHead->pNext = NULL;
pHead->value = value;
pHead->pLast = NULL;
#endif
#ifdef LoopListMode
pHead->pNext = pHead;
pHead->value = value;
pHead->pLast = pHead;
#endif
return 0;
}
/**
* @name List_NodeCnt.
* @brief Get list counters.
* @param ListNode * pHead: Head of the list.
* @retval length : list counters.
* @author Jiao Wo Yi Sheng Xiao Ming Ge.
* @Date 2018.5.30.
**/
static uint32_t List_NodeCnt(ListNode *pHead)
{
ListNode * next = pHead;
uint32_t length = 0;
#ifdef LoopListMode
while(next->pNext != pHead)
{length ++;
next = next->pNext;}
#endif
#ifndef LoopListMode
while(next->pNext != NULL)
{length ++;
next = next->pNext;}
#endif
return length;
}
uint32_t List_GetListNodeCnt(ListNode *pHead)
{
return (List_NodeCnt(pHead));
}
/**
* @name List_InsertNode.
* @brief Insert a value at node in list.
* @param ListNode * pHead: Head of the list.
uint32_t node : The place where you insert the value in the list.
uint32_t value: Value you will insert.
* @retval 0 : Succeed.
1 : You can't insert value in front of the head.
2 : The current list length is langer than MaxListLength.
3 : Head of list is NULL
* @author Jiao Wo Yi Sheng Xiao Ming Ge.
* @Date 2018.5.30
**/
ListState List_InsertNode(ListNode *pHead,const uint32_t node ,const uint32_t value)
{
ListNode * curr = (ListNode *)malloc(sizeof(ListNode));
ListNode * next = pHead;
uint32_t temp = 0,length = 0;
if(pHead == NULL)
return 3;
length = List_GetListNodeCnt(next);
if(length > MaxListLength)
return 2;
if(node == 0)
return 1;
/* 4 : The insert node is beyond current list length. */
// if(node > ListLength)
// return 4;
#ifdef SingleListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == NULL)
break;
next = next->pNext;
}
curr->pNext = next->pNext;
curr->value = value;
next->pNext = curr;
#endif
#ifdef DoubleListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == NULL)
break;
next = next->pNext;
}
curr->value = value;
curr->pLast = next;
curr->pNext = next->pNext;
if(next->pNext != NULL)
next->pNext->pLast = curr;
next->pNext = curr;
#endif
#ifdef LoopListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == pHead)
break;
next = next->pNext;
}
curr->value = value;
curr->pLast = next;
curr->pNext = next->pNext;
next->pNext->pLast = curr;
next->pNext = curr;
#endif
return 0;
}
/**
* @name List_DeleteNode.
* @brief Delete a node in list.
* @param ListNode * pHead: Head of the list.
uint32_t node : The place where you delete the value in the list.
* @retval 0 : Succeed.
1 : The delete node is beyond current list length.
2 : The current list length is langer than MaxListLength.
3 : The head of the list can't be deleted.
4 : Head of list is NULL
* @author Jiao Wo Yi Sheng Xiao Ming Ge.
* @Date 2018.5.30
**/
ListState List_DeleteNode(ListNode *pHead,const uint32_t node)
{
ListNode * next = pHead;
ListNode * curr;
uint32_t temp = 0;
uint32_t length = 0;
if(pHead == NULL)
return 4;
length = List_GetListNodeCnt(next);
if(length > MaxListLength)
return 2;
if(node > length)
return 1;
if(node == 0)
return 3;
#ifdef SingleListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == NULL)
break;
next = next->pNext;
}
curr = next->pNext;
next->pNext = curr->pNext;
free(curr);
return 0;
#endif
#ifdef DoubleListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == NULL)
break;
next = next->pNext;
}
curr = next->pNext;
curr->pNext->pLast = next;
next->pNext = curr->pNext;
free(curr);
return 0;
#endif
#ifdef LoopListMode
for(temp = 0;temp < node - 1;temp++)
{
if(next->pNext == pHead)
break;
next = next->pNext;
}
curr = next->pNext;
curr->pNext->pLast = next;
next->pNext = curr->pNext;
free(curr);
return 0;
#endif
}
/**
* @name List_DeleteVal.
* @brief Delete a value list.
* @param ListNode * pHead: Head of the list.
uint32_t value: The value which you delete in the list.
* @retval 0 : Succeed.
1 : The delete node is beyond current list length.
2 : Head of list is NULL
* @author Jiao Wo Yi Sheng Xiao Ming Ge.
* @Date 2018.5.30
**/
ListState List_DeleteVal(ListNode *pHead, const uint32_t value)
{
ListNode *next = pHead;
uint32_t i = 0;
uint32_t temp = 0;
uint32_t length = 0;
if(pHead == NULL)
return 2;
length = List_GetListNodeCnt(next);
do
{
i++;
next = next->pNext;
if(next->value == value)
{
List_DeleteNode(pHead,i - temp);
temp ++;
}
}while(ivalue == value)
{
temp ++;
List_InsertNode(&ListResult,temp,i);
}
i++;
next = next->pNext;
}while(i