嵌入式学习之路(二十二)——数据结构(4)
一。数据结构的实现----单向链表
今天我们来写一下单向链表的程序,在面试笔试中可能比较喜欢考链表
/*************************************************
**
** 文件名称:nl_test.c
** 文件功能:单向链表的各种功能实现
** 文件作者:紫瞳标
** 文件时间:2014-1-8
** 功能简介:1.正向打印
** 2.反向打印
** 3.逆转链表
** 4.遍历一次,找出链表的中间值,偶数时取左边的
**
*************************************************/
#include "node_list.h"
int main()
{
LIST list;
list_init(&list);/*初始化链表*/
list_append(&list,23);/*追加23*/
list_append(&list,33);/*追加33*/
list_append(&list,43);/*追加43*/
list_append(&list,53);/*追加53*/
printf("该链表有%d个元素\n",list_size(&list));
printf("正向打印结果为\n");
list_print(&list);/*正向打印*/
printf("反向打印结果为\n");
list_rprint(&list);/*反向打印*/
list_reverse(&list);/*逆转链表*/
printf("逆转后正向打印\n");
list_print(&list);
printf("中间值是%d\n",list_middle(&list));/*取中间值*/
list_deinit(&list);
return 0;
}
/*************************************************
**
** 文件名称:node_list.c
** 文件功能:单向链表的各种操作
** 文件作者:紫瞳标
** 文件时间:2014-1-8
**
*************************************************/
#include <stdlib.h>
#include "node_list.h"
/*************************************************
**
** 函数名称:creat_node()
** 函数功能:创建新的节点
** 函数形参:新建存入的数据
** 返回值 :节点结构体指针
**
*************************************************/
NODE_LIST * create_node(int data)
{
NODE_LIST * node = malloc(sizeof(NODE_LIST));
node->data = data;
node->next = NULL;
return node;
}
/*************************************************
**
** 函数名称:destroy_node()
** 函数功能:销毁节点
** 函数形参:删除的结构体指针
** 返回值 :节点结构体指针
**
*************************************************/
NODE_LIST * destroy_node(NODE_LIST* node)
{
NODE_LIST *temp = node->next;
free(node);
return temp;
}
/*************************************************
**
** 函数名称:list_init()
** 函数功能:链表的初始化
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
void list_init(LIST *list)
{
list->head = NULL;
list->tail = NULL;
}
/*************************************************
**
** 函数名称:list_deinit()
** 函数功能:释放剩余的节点,回到初始状态
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
void list_deinit(LIST *list)
{
while(list->head)
{
list->head = destroy_node(list->head);
}
list->tail = NULL;
}
/*************************************************
**
** 函数名称:list_append()
** 函数功能:追加节点数据
** 函数形参:链表的结构体指针,追加的数据
** 返回值 :无
**
*************************************************/
void list_append(LIST* list ,int data)
{
NODE_LIST *node = create_node(data);
/*尾节点存在,直接放在尾节点后面*/
if(list->tail)
{
list->tail->next = node;
}
/*空的链表*/
else
list->head = node;
/*无论是否是空的链表,都将这个节点变成尾节点,实现追加*/
list->tail = node;
}
/*************************************************
**
** 函数名称:list_size()
** 函数功能:统计链表中的个数
** 函数形参:链表的结构体指针
** 返回值 :链表中的个数
**
*************************************************/
size_t list_size(LIST* list)
{
int size = 0;
NODE_LIST *node = NULL;/*用一个结点遍历*/
/*不能随便改变list的内容*/
for(node = list->head;node;node = node->next)
{
++size;
}
return size;
}
/*************************************************
**
** 函数名称:list_print()
** 函数功能:正向打印
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
void list_print(LIST* list)
{
NODE_LIST *node = NULL;
for(node = list->head;node;node = node->next)
{
printf("%d ",node->data);
}
printf("\n");
}
/*************************************************
**
** 函数名称:rprint()
** 函数功能:反向打印节点的递归函数,实现反向打印
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
static void rprint(NODE_LIST *head)
{
if(head)
{
rprint(head->next);
printf("%d ",head->data);
}
}
/*************************************************
**
** 函数名称:list_rprint()
** 函数功能:反向打印链表
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
void list_rprint(LIST* list)
{
rprint(list->head);
printf("\n");
}
/*逆转以参数head的目标节点为首的子链表*/
/*************************************************
**
** 函数名称:reverse()
** 函数功能:逆转节点的递归函数
** 函数形参:节点的结构体指针
** 返回值 :无
**
*************************************************/
static void reverse(NODE_LIST *head)
{
if(head && head->next)
{
reverse(head->next);
head->next->next = head;
head->next = NULL;
}
}
/*************************************************
**
** 函数名称:list_reverse()
** 函数功能:逆转单向链表
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
void list_reverse(LIST* list)
{
reverse(list->head);
NODE_LIST *temp = list->head;
list->head = list->tail;
list->tail = temp;
}
/*取链表的中间值,只能遍历一次*/
/*利用烧绳子的思路*/
/*一个指针一次跳一个,一个指针一次跳两个*/
/*跳两个指针的到底,mid指针就到中点*/
/*************************************************
**
** 函数名称:list_middle()
** 函数功能:取链表的中间值
** 函数形参:链表的结构体指针
** 返回值 :无
**
*************************************************/
int list_middle(LIST* list)
{
NODE_LIST *mid = NULL,*node = NULL;
for(mid=node=list->head;node->next&&node->next->next;
node=node->next->next)
{
mid = mid->next;
}
return mid->data;
}
/*************************************************
**
** 文件名称:node_list.h
** 文件功能:node_list.c
** 文件作者:紫瞳标
** 文件时间:2014-1-8
**
*************************************************/
#ifndef _NODE_LIST_H
#define _NODE_LIST_H
#include <stdio.h>/*写在头文件了*/
/*节点*/
typedef struct NodeList {
int data;/*数据*/
struct NodeList *next;/*后指针*/
} NODE_LIST;
typedef struct List {
NODE_LIST *head;/*头指针*/
NODE_LIST *tail;/*尾指针*/
} LIST;
NODE_LIST * create_node(int );/*创建节点*/
NODE_LIST * destroy_node(NODE_LIST*);/*销毁节点*/
void list_init(LIST *);/*初始化*/
void list_deinit(LIST *);/*清空*/
void list_append(LIST* ,int);/*追加*/
size_t list_size(LIST*);/*测长*/
void list_print(LIST*);/*正向打印*/
void list_rprint(LIST*);/*反向打印*/
void list_reverse(LIST*);/*逆转链表*/
int list_middle(LIST*);/*取单向链表的中间值,时间复杂度不能超过O(N)级*/
#endif
makefile 如下
nl:node_list.o nl_test.o
gcc node_list.c nl_test.o -o nl
node_list.o:
gcc -c node_list.c
nl_test.o:
gcc -c nl_test.c
clean:
rm nl nl_test.o node_list.o
结果演示如下
:~/csdn/day20/node_list$ make
gcc -c node_list.c
gcc -c nl_test.c
gcc node_list.c nl_test.o -o nl
:~/csdn/day20/node_list$ ./nl
该链表有4个元素
正向打印结果为
23 33 43 53
反向打印结果为
53 43 33 23
逆转后正向打印
53 43 33 23
中间值是43