单向链表是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过顺序读取从头部开始;链表是使用指针进行构造的列表;
list.h
#ifndef LIST_H_INCLUDE
#define LIST_H_INCLUDE
#include <sys/types.h>
/*节点*/
typedef struct LIST_NODE
{
int data;
struct LIST_NODE *next;
}list_node;
/*链表*/
typedef struct LIST{
list_node *head;
list_node *tail;
list_node *frwd;
}LIST;
/*初始化链表*/
void list_init(LIST *list);
/*清空链表*/
void list_deinit(LIST *list);
/*判空*/
int list_empty(LIST *list);
/*添加节点*/
void list_append(LIST *list,int data);
/*迭代*/
void list_iteration(LIST *list);
/*元素数量*/
size_t list_size(LIST *list);
/*正向输出*/
void list_print(LIST *list);
/*反向输出*/
void list_rprint(LIST *list);
/*逆转链表*/
void list_reverse(LIST *list);
/*取中间值*/
int list_mid(LIST *list);
#endif
头文件包含功能为
链表的初始化
链表的清除
判空
追加节点
迭代
统计元素的数量
正向输出
反向输出(递归实现)
逆转链表(递归实现)
去中间值
list.c
#include"list.h"
#include<stdio.h>
#include<stdlib.h>
/*创建节点*/
static list_node* creart_node(int data)
{
list_node* node=malloc(sizeof(list_node));
node->data=data;
node->next=NULL;
return node;
}
/*删除节点*/
static list_node* destory_node(list_node* node)
{
list_node* next=node->next;
free(node);
return next;
}
/*初始化链表*/
void list_init(LIST *list)
{
list->head=NULL;
list->tail=NULL;
list->frwd=NULL;
}
/*清除链表*/
void list_deinit(LIST *list)
{
while(list->head)
list->head=destory_node(list->head);
list->tail=NULL;
list->frwd=NULL;
}
/*判空*/
int list_empty(LIST *list)
{
return !list->head && !list->tail;
}
/*增加节点*/
void list_append(LIST *list,int data)
{
list_node* node=creart_node(data);
if(list->tail)
list->tail->next=node;
else
list->head=node;
list->tail=node;
}
/*开始迭代*/
void list_iteration(LIST *list)
{
list->frwd=list->head;
}
/*数量*/
size_t list_size(LIST *list)
{
size_t size=0;
list_node* find=list->head;
for(;find;find=find->next)
size++;
return size;
}
/*正向打印*/
void list_print(LIST *list)
{
list_node *node=list->frwd;
for(;node;node=node->next)
printf("%d\t",node->data);
}
/*由于单向没有前节点,实现反向打印可利用递归*/
/*原理*/
void rtail(list_node* frwd)
{
if(frwd)
{
rtail(frwd->next);
printf("%d\t",frwd->data);
}
}
/*实现原理*/
void list_rprint(LIST *list)
{
rtail(list->frwd);
}
/*逆转函数*/
void reverse(list_node* head)
{
if(head&&head->next)
{
reverse(head->next);
/*其实空节点作用就是存当前的头结点*/
head->next->next=head;
/* 没逆转之前 1->2->3->4->NULL*/
/*当前head 在4(head)那个位置 head->NULL */
/*逆转一个节点后后 1->2->3<-4 */
head->next=NULL;
}
}
void list_reverse(LIST *list)
{
/*随着递归的结束,每个节点也逆转完了*/
reverse(list->head);
/*逆转完之后,head的next是空的,tail的next是有数据的节点*/
list_node* temp=list->head;
/*所以正常从head开始顺序打印的话,需要将逆转后的head和tail换一下*/
list->head=list->tail;
list->tail=temp;
list->frwd=list->head;
}
int list_mid(LIST *list)
{
list_node* node=NULL,*mid=NULL;
for(node=mid=list->frwd;node->next&&node->next->next;mid=mid->next,node=node->next->next);
return mid->data;
}
int main()
{
int i;
LIST list;
list_init(&list);
for(i=0;i<5;i++)
list_append(&list,i+1);
list_iteration(&list);
printf("正向打印\n");
list_print(&list);
printf("\n");
printf("反向打印\n");
list_rprint(&list);
printf("\n");
list_print(&list);
printf("\n");
list_reverse(&list);
printf("逆转后\n");
list_print(&list);
printf("\n");
list_deinit(&list);
return 0;
}
可能相对较难理解的是逆转链表那个功能。
下面画图描述逆转的过程
具体可结合代码和注释理解。