线性链表是数据结构中最常见,最常用的结构之一,其动态添加与删除优越性能在很多OS的任务调度中经常被使用到。通过最近的学习与归纳,有不小收获,整理一些常用的接口与实现如下:
1.link_list* create_list(void)
创建链表,并包头结点,头结点内容为链表长度(或节点数)
2. STATUS head_insert( link_list* list,int index,int data) 链表头插接口,index需从第二个节点开始,因为第一个节点是保留节点(存储链表长度信息)
3.STATUS tail_insert( link_list* list,int index,int data) 链表尾插接口,index需从第一个节点开始
4. STATUS get_node( link_list* list, int index, int* node_data) 获取节点内容接口;
5.STATUS get_middle_node( link_list*list, int* node_data) 获取中间节点内容接口,采用的是快慢指针的算法。具体实现,定义快慢两个指针,快指针步长为2,慢指针步长为1,当快指 针到达链尾时,慢指针指向的就是中间指针。 注:快慢指针的用法在链表里用的很多。
6.STATUS get_back_k_node( link_list*list,int k, int* node_data) 获取距离链尾第K个节点内容,采用的也是快慢指针的算法。具体实现,定义快慢两个指针,快指针先移至第K个节点,然后快慢指针同时移动,当快针到达链尾时,慢指针指向的就是距离链尾第K个节点。
7.STATUS delect_node( link_list* list,int index) 删除节点,这里有个地方要注意,被删除的节点一定要释放,否则就会造成内存泄漏
8.STATUS clear_list( link_list*list) 清空链表,只保留头结点,也是要注意释放内存
9.STATUS show_list_content(link_list*list) 打印链表内容
详细代码,需要的可以直接CV。
#ifndef __LIST_H__
#define __LIST_H__
/**************** include ********************/
#include "stdint.h"
/**************** define ********************/
/**************** struct ********************/
typedef struct list_node_t
{
int data;
list_node_t* p_next;
}link_list;
typedef enum
{
FINE,
LIST_SHORT,
NODE_NO_EXIT
} STATUS;
/**************** parameter *****************/
//struct list_node_t list_node,*p_list_node;
/**************** function ********************/
link_list* create_list(void);
STATUS head_insert( link_list* list,int index,int data);
STATUS tail_insert( link_list* list,int index,int data);
STATUS get_node( link_list* list, int index, int* node_data);
STATUS get_middle_node( link_list*list, int* node_data);
STATUS get_back_k_node( link_list*list,int k, int* node_data);
STATUS delect_node( link_list* list,int index);
STATUS clear_list( link_list*list);
STATUS show_list_content(link_list*list);
#endif /*__LIST_H__*/
/**************** (.h) end file *******************/
/* Includes ------------------------------------------------------------------*/
#include "list.h"
#include "stdio.h"
#include "stdlib.h"
/* prama define discrible -----------------------------------------------------*/
/* strcuct discrible --------------------------------------------------------*/
/* prama discrible ---------------------------------------------------------*/
/* private fucntion declaration --------------------------------------------*/
/******************************************************************************
* @Function: link_list* create_list(void)
* @Discrible: 创建空链表,返回链表头指针
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
link_list *create_list(void)
{
link_list *head;
head = (link_list *)malloc(sizeof(link_list));
head->data = 1;
head->p_next = NULL;
return head;
}
/******************************************************************************
* @Function: STATUS head_insert(link_list* list,int index, int data)
* @Discrible: index 位置前插入元素
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS head_insert(link_list *list, int index, int data)
{
int i = 1;
struct list_node_t *list_node, *pre_node;
pre_node = list;
/* 节点头插入,需要从第二个节点开始,第一个节点是不使用的节点,存储的是链表长度信息*/
if (index < 2)
{
return LIST_SHORT;
}
/*头插算法实现是找到需要头插节点的前一个节点进行尾插*/
while ((i < (index - 1)) && pre_node && pre_node->p_next)
{
pre_node = pre_node->p_next;
i++;
}
/*如果节点为空,则说明节点不存在*/
if ((!pre_node) || (!pre_node->p_next))
{
return NODE_NO_EXIT;
}
/*创建新节点*/
list_node = (link_list *)malloc(sizeof(link_list));
list_node->data = data;
/*插入节点*/
list_node->p_next = pre_node->p_next;
pre_node->p_next = list_node;
/*头结点计数加1*/
pre_node->data++;
return FINE;
}
/******************************************************************************
* @Function: STATUS tail_insert(link_list* list,int index,int data)
* @Discrible: index 位置后插入元素
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS tail_insert(link_list *list, int index, int data)
{
int ret = 0;
int i = 1;
struct list_node_t *list_node, *pre_node;
pre_node = list;
// 节点尾插入,需要从第一个节点开始,第一个节点是不使用的节点,存储的是链表长度信息
if (index < 1)
{
return LIST_SHORT;
}
while ((i < index) && pre_node)
{
pre_node = pre_node->p_next;
i++;
}
/*如果节点为空,则说明节点不存在*/
if (!pre_node)
{
return NODE_NO_EXIT;
}
/*创建新节点*/
list_node = (link_list *)malloc(sizeof(link_list));
list_node->data = data;
/*插入节点*/
list_node->p_next = pre_node->p_next;
pre_node->p_next = list_node;
/*头结点长度+1*/
pre_node->data++;
return FINE;
}
/******************************************************************************
* @Function: STATUS get_node(link_list* list, int index)
* @Discrible: 获取index节点数据
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS get_node(link_list *list, int index, int *node_value)
{
int ret = 0;
struct list_node_t *pre_node = list;
while((index-- > 1) && pre_node)
{
pre_node = pre_node->p_next;
}
if(!pre_node)
{
node_value = NULL;
return NODE_NO_EXIT;
}
*node_value = pre_node->data;
return FINE;
}
/******************************************************************************
* @Function: STATUS get_middle_node(link_list *list)
* @Discrible: 获取中间节点数值
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS get_middle_node(link_list *list,int *node_value)
{
int ret = 0;
struct list_node_t *fast_point,*slow_point,*pre_list_node;
fast_point = list;
slow_point = list;
pre_list_node = list;
/*取中间节点的值,链表长度不小于3*/
if((!pre_list_node) && (!pre_list_node->p_next) && (!pre_list_node->p_next->p_next))
{
return LIST_SHORT;
}
/*算法原理,快指针是慢指针的两倍,当快指针走到链位时,慢指针刚好走到一半*/
while(fast_point&&fast_point->p_next)
{
fast_point = fast_point->p_next->p_next;
slow_point = slow_point->p_next;
}
*node_value = slow_point->data;
return FINE;
}
/******************************************************************************
* @Function: STATUS get_back_k_node(link_list *list, int k, int* node_data)
* @Discrible: 获取倒数第K个节点的数值
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS get_back_k_node(link_list *list, int k, int* node_data)
{
int ret = 0;
struct list_node_t *fast_point,*slow_point,*pre_list_node;
fast_point = list;
slow_point = list;
pre_list_node = list;
/*先将快指针移但比慢指针多K个节点的位置*/
while((k-->0) && fast_point)
{
fast_point = fast_point->p_next;
}
if((!fast_point))
{
return LIST_SHORT;
}
/*然后同时移动快慢指针,当快指针到达链尾时,慢指针就在距离链尾K个节点的位置*/
while(fast_point)
{
fast_point = fast_point->p_next;
slow_point = slow_point->p_next;
}
*node_data = slow_point->data;
return FINE;
}
/******************************************************************************
* @Function: STATUS delect_node(link_list *list, int index)
* @Discrible: 删除某个节点
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS delect_node(link_list *list, int index)
{
int ret = 0;
struct list_node_t *pre_list_node,*list_node,*free_list_node;
pre_list_node = list;
/*节点删除必须从第二个节点开始,因为第一个节点是存储的长度信息,不可用*/
if(index < 2 )
{
return LIST_SHORT;
}
while(pre_list_node && (index-- > 2))
{
pre_list_node = pre_list_node->p_next;
}
if((!pre_list_node))
{
return NODE_NO_EXIT;
}
/*删除节点头结点计数减1*/
list_node = pre_list_node->p_next->p_next;
free_list_node = pre_list_node->p_next;
pre_list_node->p_next = list_node;
pre_list_node->data--;
/*释放删掉节点的空间*/
free(free_list_node);
free_list_node = NULL ;
return FINE;
}
/******************************************************************************
* @Function: STATUS clear_list(link_list *list)
* @Discrible: 清空链表
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS clear_list(link_list *list)
{
int ret = 0;
struct list_node_t *list_node,*free_list_node;
/*清空链表,只保留表头的信息*/
list_node = list->p_next;
list->data = 1;
list->p_next = NULL;
while(list_node)
{
free_list_node = list_node;
list_node = list_node->p_next;
free(free_list_node);
free_list_node = NULL;
}
return FINE;
}
/******************************************************************************
* @Function: STATUS show_list_content(link_list *list)
* @Discrible: 打印链表内容
* @Param:
* @Return:
* @Others:
******************************************************************************
* @Recode date version author modify
* ------------------------------------------------------------------
* 20190605 V1.0 VINCENT Create
*
*******************************************************************************/
STATUS show_list_content(link_list *list)
{
int ret = 0;
link_list *pre_node = list;
printf("\r\n----------- beagin -----------\r\n");
while (pre_node)
{
printf("%d ", pre_node->data);
pre_node = pre_node->p_next;
}
printf("\r\n----------- end -----------\r\n");
return FINE;
}
/************************ (C) END OF FILE ************************************/