linked list, list, list item

linked list, list, list item

FreeRTOS lists and list items

  1. List_t

    
    
    //List_t 列表
    
    typedef struct xLIST
    
    {
          
          
    
      listFIRST_LIST_INTEGRITY_CHECK_VALUE    //校验值
    
      volatile UBaseType_t uxNumberOfItems;   // 列表中的列表项数量:用于记录列表中列表项的个数(不包含 xListEnd)
    
      ListItem_t * configLIST_VOLATILE pxIndex; // 用于遍历列表项的指针:用于指向列表中的某个列表项,一般用于遍历列表中的所有列表项 
    
      MiniListItem_t xListEnd;          // 末尾列表项:成员变量 xListEnd 是一个迷你列表项,排在最末尾 
    
      listSECOND_LIST_INTEGRITY_CHECK_VALUE   //< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1.
    
    } List_t;
    
    
    
  2. ListItem_t

    //ListItem_t 列表项
    
    struct xLIST_ITEM
    {
          
          
      listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE      
    
      configLIST_VOLATILE TickType_t xItemValue;      		//列表项的值  
    
      struct xLIST_ITEM * configLIST_VOLATILE pxNext;   	//下一个列表项  
    
      struct xLIST_ITEM * configLIST_VOLATILE pxPrevious; 	//上一个列表项 
    
      void * pvOwner;                   					//列表项的拥有者 
    
      struct xLIST * configLIST_VOLATILE pxContainer;   	//列表项所在列表 
    
      listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE      
    
    };
    
  3. Insertion of the vListInsert list (essentially the use of a doubly linked list)

    Sort and insert according to the xItemValue in the Item list item, the larger the xItemValue, the closer to xListEnd

    void vListInsert( List_t * const pxList, ListItem_t * const pxNewListItem ) 
    {
          
             
        /*pxList 列表项要插入的列表 pxNewListItem 要插入的列表项*/
     	ListItem_t * pxIterator; /* 临时索引变量 */
    	const TickType_t  xValueOfInsertion  =  pxNewListItem->xItemValue; //获取插入的列表项值	
    	listTEST_LIST_INTEGRITY( pxList ); 							/* 检查参数是否正确 */
    	listTEST_LIST_ITEM_INTEGRITY( pxNewListItem ); 				/* 如果待插入列表项的值为最大值 */ 
    	 /*将新的列表项插入到列表,根据xItemValue的值升序插入列表。*/
       
        if( xValueOfInsertion == portMAX_DELAY ) //portMAX_DELAY列表项的值为最大值
     	{
          
           
             /* 如果列表项的值等于portMAX_DELAY,即列表项为最大值,则插入末尾 */
    		pxIterator = pxList->xListEnd.pxPrevious; 				/* 插入的位置为列表 xListEnd 前面 */ 
    	} 
        
        else  /*遍历列表中的列表项,找到插入的位置*/
    	{
          
          
    		for(  pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); 	 
    		         pxIterator->pxNext->xItemValue <= xValueOfInsertion; 
    		         pxIterator = pxIterator->pxNext  )
             /*
             pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); //
             */
            {
          
          
                 /* There is nothing to do here, just iterating to the wanted insertion position. */
            }
    	} 
        /*待插入的列表项插入过程*/
    	pxNewListItem->pxNext = pxIterator->pxNext;			/* 将待插入的列表项插入指定位置 */ 
     	pxNewListItem->pxNext->pxPrevious = pxNewListItem; 
    	pxNewListItem->pxPrevious = pxIterator; 
    	pxIterator->pxNext = pxNewListItem; 
        /* Remember which list the item is in.  This allows fast removal of the item later. */
    	pxNewListItem->pxContainer = pxList; 				/* 更新待插入列表项所在列表 */ 
    	( pxList->uxNumberOfItems )++;						/* 更新列表中列表项的数量 */ 
    }
    

Reference article: Analysis of list and list item insertion functions in FreeRTOS (https://blog.csdn.net/qq_20222919/article/details/102936067)

FreeRTOS lists and list items

p98q20x.jpg

If the current list items are as follows:

At this point we want to insert 50 into the list

At this time, pxNewListItem points to item 50, and pxIterator points to item 40.

It can also be seen from the above for loop that
pxIterator->pxNext->xItemValue <= xValueOfInsertion;
the value in the list is less than or equal to the value to be inserted, and the insertion point continues to point to the next one.

At this time, the value to be inserted is 50, which will be compared with the values ​​20, 30, 40, and 60 in the list in turn. When the comparison reaches 60, the value of the insertion point is 60, which is greater than the value to be inserted. 50, at this time the for loop Exit, and the insertion point points to item 40.
The state of the list at this time is shown in the figure below

Down to start the list insertion operation.

   pxNewListItem->pxNext = pxIterator->pxNext;//50->next->60

Assign the next list item pointed to by the insertion point to the next item of the newly inserted list item

At this time, the next item of list item 50 points to list item 60.

pxNewListItem->pxNext->pxPrevious = pxNewListItem;//pxNewListItem->pxNext就是60 60->pre ->50

Sets the item immediately preceding the newly inserted list item's next item to the newly inserted list item.

That is to say, the previous list item of list item 60 points to 50 at this time.

pxNewListItem->pxPrevious = pxIterator;

Down sets the previous list item of the newly inserted list item as the insertion point.

At this time, the previous item of list item 50 points to 40.

 pxIterator->pxNext = pxNewListItem;

Point the newly inserted list item to the next item at the insertion point

Now the next item of list item 40 is list item 50, and the next item of list item 50 is 60. The item preceding list item 60 is list item 50 , and the item preceding list item 50 is list item 40 .
pxNewListItem->pvContainer = ( void * ) pxList :
After insertion, the list item member variable pvContainer records which list this list item belongs to.
pxList->uxNumberOfItems : Add 1 to the number of list members.
The list item 50 has just been successfully inserted into the list like this, and the process of inserting is exactly to disconnect the insertion point from the following connection item, and then reconnect on the new insertion item. Connecting the newly inserted item to the disconnected link item.

C language linked list basics

Blog reference https://yufengbiji.com/posts/data-structures-02

  1. Linked list creation

    Define a structure representing a node

    struct node {
          
          
        /* 后继节点 */
        struct node *next;
        /* 值 */
        int data;
    };
    
    定义结点结构体
    typedef struct node
    {
          
          
        /* data:数据域*/
        int num;
        int score;
        char name[20];
        /* point:指针域 指针需要指向的地址 后继节点*/  
        struct node *next;
    } Node;
    

    In the following code writing, Nodeit is equivalent to struct node. For example, if we use this structure to create a new node, Node *new_nodeit is equivalent struct node *new_nodeto

    single linked list node

​ Representation of a single linked list

Singly linked list is the linked representation and implementation of linear list . Link the nodes to form a singly linked list.

​ Creating a single linked list

list * create_list()
{
    
    
    /* 创建一个新的节点,由于使用了typedef关键字,此处 node *head与struct node *head等价    */
    list *head = (list *)malloc(sizeof(list));
    if(head==NULL) return NULL;
    /* 初始化节点 */
    head->data = 0; // 头结点数据域,我们用来表示链表长度
    head->next = NULL; 
    return head;
}

head pointer

This function creates a singly linked list and returns the head pointer. The head pointer is a pointer to the address of the head node, which is the same type as the pointer to the next node in the node.
First, we use mallocthe function to open up a listblock of memory, and return a pointer to the first address of the memory block, and assign this pointer to the head pointer variable.
Then, judge whether the pointer is empty, if it is empty, it means that the memory application failed (generally not).
Then, initialize the node.
Finally, the function returns the head pointer, end.

Why set the head node?
The data field of the head node is generally meaningless. It is set here for the convenience of later insertion and deletion operations. The head node is not necessary for the linked list.
The first element node after the head node is called the head node

// 链表的创建
void link_creat_head(Node ** p_head,Node *p_new)
{
    
    
    Node *p_mov  = *p_head; //当第一次加入链表为空时,head执行p_new
    if (*p_head == NULL)
    {
    
    
        *p_head = p_new;
         p_new->next = NULL;
    } 
    else //第二次及以后加入链表
    {
    
    
        while (p_mov->next!=NULL) //找到原有链表的最后一个节点
        {
    
    
            p_mov = p_mov->next;
        }

        p_mov->next = p_new; //将新申请的节点加入链表
        p_new->next = NULL;        
    }
    
}
//链表的遍历
void link_print(Node *head)
{
    
    
    Node *p_mov;    //定义新的指针保存链表的首地址,防止使用head改变原本链表
    p_mov = head;   //当指针保存最后一个结点的指针域为NULL时,循环结束
    while(p_mov!=NULL)
    {
    
    
        //先打印当前指针保存结点的指针域
        printf("num=%d score=%d name:%s\n",p_mov->num,\
               p_mov->score,p_mov->name);
        //指针后移,保存下一个结点的地址
        p_mov = p_mov->next;
    }
}

//链表的释放
void link_free(Node **p_head)
{
    
    
    //定义一个指针变量保存头结点的地址
    Node *pb=*p_head;
    while(*p_head!=NULL)
    {
    
    
        //先保存p_head指向的结点的地址
        pb=*p_head;
        //p_head保存下一个结点地址
        *p_head=(*p_head)->next;
        //释放结点并防止野指针
        free(pb);
        pb = NULL;
    }
}
  1. Basic operation of singly linked list

    2.1 Insertion of singly linked list

    2.2 Deletion of singly linked list

    2.3 Lookup of singly linked list

    First compare whether the data field of the first node is the desired data, if it is, return directly, if not, continue to search for the next node, if there is no matching data when reaching the last node, it means to search data does not exist

//链表的查找
//按照num查找
Node * link_search_num(Node *head,int num)
{
    
    
    Node *p_mov;
    //定义的指针变量保存第一个结点的地址
    p_mov=head;
    //当没有到达最后一个结点的指针域时循环继续
    while(p_mov!=NULL)
    {
    
    
        //如果找到是当前结点的数据,则返回当前结点的地址
        if(p_mov->num == num)//找到了
        {
    
    
            return p_mov;
        }
        //如果没有找到,则继续对比下一个结点的指针域
        p_mov=p_mov->next;
    }

    //当循环结束的时候还没有找到,说明要查找的数据不存在,返回NULL进行标识
    return NULL;//没有找到
}
//按照name查找
Node * link_search_name(Node *head,char *name)
{
    
    
    Node *p_mov;
    p_mov=head;
    while(p_mov!=NULL)
    {
    
    
        if(strcmp(p_mov->name,name)==0)//找到了
        {
    
    
            return p_mov;
        }
        p_mov=p_mov->next;
    }
    return NULL;//没有找到
}
//链表的插入:按照num的顺序插入
void link_insert_num(Node **p_head,Node *p_new)
{
    
    
    Node *pb,*pf;
    pb=pf=*p_head;
    if(*p_head ==NULL)// 链表为空链表
    {
    
    
        *p_head = p_new;
        p_new->next=NULL;
        return ;
    }
    while((p_new->num >= pb->num)  && (pb->next !=NULL) )
    {
    
    
        pf=pb;
        pb=pb->next;
    }

    if(p_new->num < pb->num)//找到一个节点的num比新来的节点num大,插在pb的前面
    {
    
    
        if(pb== *p_head)//找到的节点是头节点,插在最前面
        {
    
    
            p_new->next= *p_head;
            *p_head =p_new;
        }
        else
        {
    
    
            pf->next=p_new;
            p_new->next = pb;
        }
    }
    else//没有找到pb的num比p_new->num大的节点,插在最后
    {
    
    
        pb->next =p_new;
        p_new->next =NULL;
    }
}


//链表的排序
void link_order(Node *head)
{
    
    
    Node *pb,*pf,temp;
    pf=head;

    if(head==NULL)
    {
    
    
        printf("The list is empty and does not need to be sorted\n");
        return ;
    }

    if(head->next ==NULL)
    {
    
    
        printf("Only one node, no sorting\n");
        return ;
    }
    while(pf->next !=NULL)  //以pf指向的节点为基准节点,
    {
    
    
        pb=pf->next ;       //pb从基准元素的下个元素开始
        while(pb!=NULL)
        {
    
    
            if(pf->num > pb->num) //判断num的大小去排序
            {
    
    
                temp=*pb;
                *pb=*pf;
                *pf=temp;

                temp.next=pb->next;
                pb->next=pf->next;
                pf->next=temp.next;
            }
            pb=pb->next;
        }
        pf=pf->next;
    }
}

//链表结点的删除
void link_delete_num(Node **p_head,int num)
{
    
    
    Node *pb,*pf;
    pb=pf=*p_head;
    if(*p_head == NULL)//链表为空,不用删
    {
    
    
        printf("The list is empty and there are no nodes to delete");\
        return ;
    }
    while(pb->num != num && pb->next !=NULL)//循环找,要删除的节点
    {
    
    
        pf=pb;
        pb=pb->next;
    }
    if(pb->num == num)//找到了一个节点的num和num相同
    {
    
    
        if(pb == *p_head)//要删除的节点是头节点
        {
    
    
            *p_head = pb->next;//让保存头结点的指针保存后一个结点的地址
        }
        else
        {
    
    
            pf->next = pb->next;//前一个结点的指针域保存要删除的后一个结点的地址
        }
        //释放空间
        free(pb);
        pb = NULL;
    }
    else//没有找到
    {
    
    
        printf("There are no nodes to delete\n");
    }
}
  1. code testing
int main()
{
    
    
    Node *head = NULL, *p_new =NULL;
    int  num,i;

    printf("Please enter the initial number of linked list:\n");
    scanf("%d",&num);
    for (i = 0;i<num;i++)
    {
    
    
        p_new = (Node*) malloc(sizeof(Node));
        printf("Iint num,socre,name \n");

        scanf("%d %d %s",&p_new->num,&p_new->score,&p_new->name);

        link_creat_head(&head,p_new);
    }
    link_print(head);

    #if 0
    Node *pb;
    while(1)
    {
    
    
        printf("Please enter the number you are looking for \n");
        scanf("%d",&num);
        pb=link_search_num(head,num);
        if(pb!=NULL)//找到了
        {
    
    
            printf("Found it. num=%d score=%d name:%s\n",pb->num,pb->score,pb->name);
        }
        else
        {
    
    
            printf("The node you were looking for was not found \n");
        }
    }
    #endif

    #if 0
    char name[32] = "";
    Node *pb;
    while(1)
    {
    
    
        printf("Please enter the name you are looking for\n");
        scanf("%s",name);
        pb=link_search_name(head,name);
        if(pb!=NULL)//找到了
        {
    
    
            printf("Found it. num=%d score=%d name:%s\n",pb->num,pb->score,pb->name);
        }
        else
        {
    
    
            printf("The node you were looking for was not found\n");
        }
    }
    #endif
    #if 0
    printf("Enter the number of the node you want to delete\n");
    scanf("%d",&num);
    link_delete_num(&head,num);

    link_print(head);
    #endif
    #if 0
    while(1)
    {
    
    
        printf("Enter the num-score-name of the node you want to insert\n");
        p_new=(Node*)malloc(sizeof(Node));//申请一个新节点
        scanf("%d %d %s",&p_new->num,&p_new->score,p_new->name);
        link_insert_num(&head,p_new);
        link_print(head);
    }
    #endif

    #if 0
    printf("***************************\n");
    link_order(head);
    link_print(head);
    #endif
    
    
    link_free(&head);
    return 0;
}

pC2iKIJ.md.png
pC2iua4.md.png
pC2inZF.md.png
pC2ieqU.md.png
pC2iZrT.md.png

Guess you like

Origin blog.csdn.net/weixin_43599390/article/details/131625210