链表框架--双向循环,带上下级

亲测可用。反正没人会看,随便写写就好了...瘪嘴 :) 

前景:在使用一些简单的LCD显示屏时,编写菜单,每次都是一个头疼的问题,甚至有些时候牵一发动全身,在想着也没有一种简单的框架,来方便菜单的执行(链表或许是一种不错的选择)

形式:对于一个菜单而言,有上一页,下一页,在某页中还可能会进入下一级,也需要退回到上一级等等,这就需要用到链表的格式,如下

typedef struct List_Node
{
  struct List_Node *ppar;
  struct List_Node *pchi;
  struct List_Node *pnxt;
  struct List_Node *plst;
  void *pdata;
  uint16_t val;

}__attribute__((aligned(1), packed))listInfo_t;

ppar为上一级(父节点),pchi为下一级(子节点),pnxt为下一页,plst为上一页,pdata为这个链表需要存储数据的指针(void *嘛,万用指针),重点是这个val,这个值就是此小型链表框架的精髓

val值:位数(个十百千万)为级数,位数里面的数字为页数,用框架来说的话如下图

 基本理念是这样,理论上是能够用满65536个数(算上0),除去最高级(6xxxxx),理论上可以最大广度可以有9页,深度是5级

使用回调函数的形式完成,把每一级看成一个双向循环的链表,然后进行嵌套,遇到下一个不是同级的就进行嵌入或者退出

接下来就是实现它

首先,定义一个结构体,往后的数据只要修改这个结构体即可,例如只修改下面的ct_ListTab

typedef struct
{
  uint16_t val;
  void *pdata;

}__attribute__((aligned(1), packed))listTabel_t;

static listInfo_t *pListHead = NULL;
listInfo_t *pListCurr = NULL;

static uint8_t st_userdata[0x10] = 
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00,
};

static const listTabel_t ct_ListTab[] =
{
	{0, NULL},
	{1, NULL},
	{11, NULL},
    {111, NULL},
	{21, (void *)st_userdata},
    {31, NULL},
    {131, NULL},
    {231, NULL},
    {41, NULL},
	{2, NULL},
	{3, NULL},
    {13, NULL},
    {4, NULL},
};

首先,实现双向链表的节点创建和节点新增

/**
 * @brief    Create a node
 * @param    void
 * @retval   true : listInfo_t*
 * @retval   fail : NULL
 */
static listInfo_t *user_CreatNode(void)
{
	listInfo_t *p = (listInfo_t*)tool_Malloc(sizeof(listInfo_t));

	if(p == NULL)
	{
		return NULL;
	}

	p->ppar = NULL;
	p->pchi = NULL;
	p->plst = NULL;
	p->pnxt = NULL;
  p->pdata = NULL;

	return p;
}

/**
 * @brief    Add a node after the current location to create a new node
 * @param    listInfo_t* The current node pointer
 * @retval   true : listInfo_t*
 * @retval   fail : NULL
 */
static listInfo_t *user_AddNode(listInfo_t *pcur)
{
	listInfo_t *pnew = user_CreatNode();

	if(pnew == NULL)
	{
		return NULL;
	}

	if(pcur == NULL)    // If the first pointer is empty, it is created as a pointer header
	{
		pcur = pnew;
		pcur->pnxt = pnew;
		pcur->plst = pnew;
	}
	else if(pcur->pnxt == pcur)	// If it is a second linked list
	{
		pcur->pnxt = pnew;
		pcur->plst = pnew;
		pnew->pnxt = pcur;
		pnew->plst = pcur;
	}
	else    // Three or more
	{
		pnew->pnxt = pcur->pnxt;
		pnew->plst = pcur;
		pcur->pnxt->plst = pnew;
		pcur->pnxt = pnew;
	}

	return pnew;
}

使用工具如下

/**
 * @brief    Calculate how many digits there are in decimal
 * @param    uint16_t decimal number
 * @retval   uint16_t uint
 */
static uint8_t tool_DecUint(uint16_t num)
{
  uint16_t data = num;
  uint8_t res = 0x00;
  
  do
  {
    res++;
    data /= 0x0A;
  }while(data);

  return res;
}

/**
 * @brief    Space request function
 * @param    uint32_t malloc size
 * @retval   void* data type
 */
void *tool_Malloc(uint32_t size)
{
  return malloc(size);
}

/**
 * @brief    Gets the number of decimal digits
 * @param    uint8_t loca
 * @retval   uint8_t muti
 */
static uint8_t user_GetTabMuti(uint8_t loca)
{
  return tool_DecUint(ct_ListTab[loca].val);
}

/**
 * @brief    Gets the largest element of the array
 * @param    void
 * @retval   uint16_t element
 */
static uint16_t user_GetTabMax(void)
{
  return sizeof(ct_ListTab) / sizeof(listTabel_t);
}

最后就是实现该功能

/**
 * @brief    Register a linked list
 * @param    uint8_t table location
 * @param    listInfo_t* parente pionter
 * @retval   true: 0x00
 * @retval   fail: negative number
 */
static int user_List_Reg(uint8_t loca, listInfo_t *ppar)
{
	listInfo_t *p = NULL;
	uint8_t i = loca;
  uint8_t enter = 0x00;

	for(i = loca; i < user_GetTabMax(); i++)
	{
		p = user_AddNode(p);
		if(p == NULL)
		{
			return -i;
		}   // An error occurs when all applications were cleared before cancellation
		else
		{
      if(i == 0x00)
      {
        pListHead = p;	// Defines the pointer header
      }
			else
			{
				pListCurr = p;	// Keep the current node
			}

  /* USER CODE BEGIN List_Init 1 */

      p->val = ct_ListTab[i].val; // Attach the page number
			p->pdata = ct_ListTab[i].pdata;

  /* USER CODE END List_Init 1 */

      if(ppar != NULL)
      {
        if(i == loca)
        {
          ppar->pchi = p;
        }   // Identify child nodes
        p->ppar = ppar; // Confirm the parent node
      }

      if((i + 0x01) < user_GetTabMax())    // The next one cannot exceed the largest array
      {
        if((user_GetTabMuti(i + 0x01)) > user_GetTabMuti(i))    // Determines whether the next bit is greater than the previous one dimension
        {
          enter = user_GetTabMuti(i); // The value of the dimension is retained
          i = user_List_Reg(i + 0x01, p); // Enter recursion

          if(enter < user_GetTabMuti(i))  // Determine whether the recursive returned dimension is the same as the loop
          {
						if((user_GetTabMuti(i + 0x01) + 0x01) == user_GetTabMuti(i))
						{
							// Make sure the next number is not a fault, such as 121 - 31
						}
						else
						{
							return i + 0x01;    // If so, offset backwards and back
						}
          }
          else
          {
            i--;    // If the same is the case, the loop is subtracted by one, because it will be added before the next loop
          }
        }
        else if(user_GetTabMuti(i + 0x01) < user_GetTabMuti(i)) // If the next dimension is judged to be smaller than the previous dimension
        {
          return i;
        }
      }
      else
      {
          
      }
		}
	}

  pListCurr = pListHead;
	return i;
}

咱们来验证一下,初始化结束之后,打印数据

log_debug("val = %d, data = %d", pListCurr->pnxt->pchi->pnxt->val, ((uint8_t *)pListCurr->pnxt->pchi->pnxt->pdata)[0x05]);

打印结果为:

-> Debug : val = 21, data = 6

故:在最后使用的时候,在使用的时候,只需要调用函数user_List_Reg(0x00, NULL),而且修改最初的那个结构体数组即可完成整个链表的改变,其他功能,就比如回到链表头啊,根据val数值找到某个链表所在的位置啊就比较简单了

毕竟~,反正没人会看

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值