注:本文的主要目的是为了记录自己的学习过程,也方便与大家做交流。
转载请注明来自: http://blog.csdn.net/ab198604/
最近突然间觉得应该补补IT技术的基础的知识,因为对这些基础知识的梳理不仅可以对自己所掌握的知识进一步巩固,无论是提高自身的技术水平方面还是从后期就业方面,都是大有裨益的,所以还是要打好基础,一步一个脚印才行,总之,知识需要有时间的积累。
从前自己并未系统的学习过计算机知识,对数据结构的认识也是一知半解,自从学了Linux系统的一些知识之后,特别是发现在linux内核中对链表的运用随处可见,由不得自己不重视,当然链表的运用范畴本身是非常广泛的,如邮件列表、内存管理、多项式计算等,所以只要掌握了链表的基础知识,就可以做到举一反三了,对类似运用场景的链表代码也就可以自然地掌握了。
链表其实有许多的种类:单向链表、双向链表、单向循环链表和双向循环链表。他们之间的复杂关系是逐步增加的,这里主要介绍单向链表这种数据结构,因为它使用最为广泛。
什么是单向链表呢?
从字面上理解,那就是“单向”+“链表”,表明这种数据结构是有方向性的,并且只有一个方向。另外,“链表”表明这种数据结构是一种链式存储结构,它不同于线性表的顺序存储结构。链表的相邻元素在物理内存中不连续,所以这种结构可以充分利用一些系统的内存碎片来完成一些事务,即如果采用链表结构有时可以解决当连续内存分配不足时的问题。既然是单向链表,那也意味着它是由各个元素之间通过一个指针彼此连接而组成的。每个元素包含两部分:数据域和一个称为next的指针域。通过采用这种结构,next的指针域将按某一个方向指向其下一个元素。最后一个元素的next指针域指向NULL,即为空,它表示链表的末尾元素,链表的第一个元素称为“头”元素。链表的示意图如下所示:
如上图所示,每个元素链接在一起形成一个链表。
单向链表的一个特性就是只能沿着next指针的方向寻找到其后续元素,如果要寻找到链表中的某个元素,只能从头到尾遍历整个链表。如果我们已经从头到尾访问到某个元素,但是此时又想访问这个元素的前几个元素,此时我们是无法进行访问,因为在我们的元素中并没有维护一个前向的链接,所以此时必须再次从头进行遍历操作才行。
简单回顾完单向链表的基本知识点后,下面我们要真枪实弹的开练了。以下是具体的代码,它包含三个部分,先对每个部分进行简单的描述说明:
list.h -->主要是单向链表的一些接口定义
list.c -->主要是对接口定义的具体细节实现
main.c -->主要是展示链表的一些简单应用
1 单链表的接口定义
- /*
- * file name: list.h
- * author: zhm
- * date: 2012-12-06
- */
- #ifndef LIST_H
- #define LIST_H
- #include <stdlib.h>
- /* define a struct for list element */
- typedef struct ListElmt_
- {
- void *data;
- struct ListElmt_ *next;
- }ListElmt;
- /* define a structure for linked list */
- typedef struct List_
- {
- int size;
- void (*match)(const void *key1, const void *key2);
- void (*destroy)(void *data);
- ListElmt *head;
- ListElmt *tail;
- }List;
- /* define public interface */
- void list_init(List *list, void(*destroy)(void *data));
- void list_destroy(List *list);
- int list_ins_next(List *list, ListElmt *elemet, const void *data);
- int list_rem_next(List *list, ListElmt *element, void **data);
- #define list_size(list) ((list)->size)
- #define list_head(list) ((list)->head)
- #define list_tail(list) ((list)->tail)
- #define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)
- #define list_is_tail(list, element) ((element) == (list)->tail ? 1 : 0)
- #define list_data(element) ((element)->data)
- #define list_next(element) ((element)->next)
- #endif
/*
* file name: list.h
* author: zhm
* date: 2012-12-06
*/
#ifndef LIST_H
#define LIST_H
#include <stdlib.h>
/* define a struct for list element */
typedef struct ListElmt_
{
void *data;
struct ListElmt_ *next;
}ListElmt;
/* define a structure for linked list */
typedef struct List_
{
int size;
void (*match)(const void *key1, const void *key2);
void (*destroy)(void *data);
ListElmt *head;
ListElmt *tail;
}List;
/* define public interface */
void list_init(List *list, void(*destroy)(void *data));
void list_destroy(List *list);
int list_ins_next(List *list, ListElmt *elemet, const void *data);
int list_rem_next(List *list, ListElmt *element, void **data);
#define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_is_head(list, element) ((element) == (list)->head ? 1 : 0)
#define list_is_tail(list, element) ((element) == (list)->tail ? 1 : 0)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next)
#endif
单向链表的操作主要有插入,删除结点,初始化链表和删除链表操作。
2 单链表的接口实现细节
- /*
- * filename: list.c
- * author: zhm
- * date: 2012-12-06
- */
- #include <stdlib.h>
- #include <string.h>
- #include "list.h"
- /* list_init */
- void list_init(List *list, void (*destroy)(void *data))
- {
- list->size = 0;
- list->destroy = destroy;
- list->head = NULL;
- list->tail = NULL;
- return;
- }
- /* list_destroy */
- void list_destroy(List *list)
- {
- void *data; //keep the data in the element of the list
- /*remove the element */
- while( list_size(list) > 0 )
- {
- if(list_rem_next(list, NULL, (void **)&data) == 0 &&
- list->destroy != NULL)
- {
- list->destroy(data);
- }
- }
- memset(list, 0, sizeof(list));
- return;
- }
- /* list_ins_next */
- int list_ins_next(List *list, ListElmt *element, const void *data)
- {
- /* Allocate storage */
- ListElmt *new_element = NULL;
- new_element = (ListElmt *)malloc(sizeof(ListElmt));
- if( new_element == NULL )
- return -1;
- new_element->data = (void *)data;
- /* Insert the element into the list */
- if( element == NULL ) //from head position to insert
- {
- if( list_size(list) == 0 ) //be care to tail
- list->tail = new_element;
- new_element->next = list->head;
- list->head = new_element;
- }
- else
- {
- if( element->next == NULL ) //be care to tail
- list->tail = new_element;
- new_element->next = element->next;
- element->next = new_element;
- }
- /*Adjust size */
- list->size++;
- return 0;
- }
- /* list_rem_next */
- int list_rem_next(List *list, ListElmt *element, void **data)
- {
- ListElmt *old_element;
- //if the list is empty
- if( list_size(list) == 0 )
- return -1;
- /* Remove the element from the list */
- if( element == NULL ) //from head to remove
- {
- *data = list->head->data; //keep the data.
- old_element = list->head;
- list->head = list->head->next;
- if( list_size(list) == 1 ) //be care to the tail
- list->tail = NULL;
- }
- else
- {
- //if the element to be removed is NULL
- if( element->next == NULL )
- return -1;
- *data = element->next->data;
- old_element = element->next;
- element->next = element->next->next;
- if( element->next == NULL ) //be care to the tail
- list->tail = element;
- }
- //free the memory
- free(old_element);
- list->size--;
- return 0;
- }
/*
* filename: list.c
* author: zhm
* date: 2012-12-06
*/
#include <stdlib.h>
#include <string.h>
#include "list.h"
/* list_init */
void list_init(List *list, void (*destroy)(void *data))
{
list->size = 0;
list->destroy = destroy;
list->head = NULL;
list->tail = NULL;
return;
}
/* list_destroy */
void list_destroy(List *list)
{
void *data; //keep the data in the element of the list
/*remove the element */
while( list_size(list) > 0 )
{
if(list_rem_next(list, NULL, (void **)&data) == 0 &&
list->destroy != NULL)
{
list->destroy(data);
}
}
memset(list, 0, sizeof(list));
return;
}
/* list_ins_next */
int list_ins_next(List *list, ListElmt *element, const void *data)
{
/* Allocate storage */
ListElmt *new_element = NULL;
new_element = (ListElmt *)malloc(sizeof(ListElmt));
if( new_element == NULL )
return -1;
new_element->data = (void *)data;
/* Insert the element into the list */
if( element == NULL ) //from head position to insert
{
if( list_size(list) == 0 ) //be care to tail
list->tail = new_element;
new_element->next = list->head;
list->head = new_element;
}
else
{
if( element->next == NULL ) //be care to tail
list->tail = new_element;
new_element->next = element->next;
element->next = new_element;
}
/*Adjust size */
list->size++;
return 0;
}
/* list_rem_next */
int list_rem_next(List *list, ListElmt *element, void **data)
{
ListElmt *old_element;
//if the list is empty
if( list_size(list) == 0 )
return -1;
/* Remove the element from the list */
if( element == NULL ) //from head to remove
{
*data = list->head->data; //keep the data.
old_element = list->head;
list->head = list->head->next;
if( list_size(list) == 1 ) //be care to the tail
list->tail = NULL;
}
else
{
//if the element to be removed is NULL
if( element->next == NULL )
return -1;
*data = element->next->data;
old_element = element->next;
element->next = element->next->next;
if( element->next == NULL ) //be care to the tail
list->tail = element;
}
//free the memory
free(old_element);
list->size--;
return 0;
}
3 测试用例代码,如下所示:
- /*
- * filename: main.c
- * author:zhm
- * date: 2012-12-06
- */
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include "list.h"
- /* destroy */
- void destroy(void *data)
- {
- printf("in destroy\n");
- free(data);
- return;
- }
- /* main */
- int main(int argc, char **argv)
- {
- ListElmt *elem_ptr = NULL;
- int i;
- int ret;
- int *data = NULL;
- /* Create a linked list */
- List list_exp;
- /* init the list */
- printf("\ninit the list:\n");
- list_init(&list_exp, destroy);
- /* insert the element */
- printf("\ncreate a list:\n");
- for(i = 0; i < 10; i++ )
- {
- data = (int *)malloc(sizeof(int));
- if( data == NULL )
- return -1;
- *data = i;
- list_ins_next(&list_exp, NULL, (void *)data);
- }
- /* now the list has 10 element, then traverse and print every element */
- elem_ptr = list_exp.head;
- for( i = 0; i < 10; i++ )
- {
- printf("%d ", *(int *)list_data(elem_ptr) );
- elem_ptr = list_next(elem_ptr);
- }
- printf("\n");
- /* Remove the element, its value of the data equal 4,then traverse and print again */
- elem_ptr = list_exp.head;
- for( i = 0; i < list_size(&list_exp); i++ )
- {
- if( *(int *)list_data(elem_ptr) == 5 )
- {
- ret = list_rem_next(&list_exp, elem_ptr, (void **)&data);
- if( ret == 0 )
- {
- destroy(data);
- }
- }
- elem_ptr = list_next(elem_ptr);
- }
- printf("after remove the element: value = 4\n");
- //traverse and print again
- elem_ptr = list_exp.head;
- for( i = 0; i <list_size(&list_exp); i++ )
- {
- printf("%d ", *(int *)list_data(elem_ptr) );
- elem_ptr = list_next(elem_ptr);
- }
- printf("\n\n");
- printf("here begin to destroy the list :\n");
- //destroy the linked list
- list_destroy(&list_exp);
- return 0;
- }
/*
* filename: main.c
* author:zhm
* date: 2012-12-06
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "list.h"
/* destroy */
void destroy(void *data)
{
printf("in destroy\n");
free(data);
return;
}
/* main */
int main(int argc, char **argv)
{
ListElmt *elem_ptr = NULL;
int i;
int ret;
int *data = NULL;
/* Create a linked list */
List list_exp;
/* init the list */
printf("\ninit the list:\n");
list_init(&list_exp, destroy);
/* insert the element */
printf("\ncreate a list:\n");
for(i = 0; i < 10; i++ )
{
data = (int *)malloc(sizeof(int));
if( data == NULL )
return -1;
*data = i;
list_ins_next(&list_exp, NULL, (void *)data);
}
/* now the list has 10 element, then traverse and print every element */
elem_ptr = list_exp.head;
for( i = 0; i < 10; i++ )
{
printf("%d ", *(int *)list_data(elem_ptr) );
elem_ptr = list_next(elem_ptr);
}
printf("\n");
/* Remove the element, its value of the data equal 4,then traverse and print again */
elem_ptr = list_exp.head;
for( i = 0; i < list_size(&list_exp); i++ )
{
if( *(int *)list_data(elem_ptr) == 5 )
{
ret = list_rem_next(&list_exp, elem_ptr, (void **)&data);
if( ret == 0 )
{
destroy(data);
}
}
elem_ptr = list_next(elem_ptr);
}
printf("after remove the element: value = 4\n");
//traverse and print again
elem_ptr = list_exp.head;
for( i = 0; i <list_size(&list_exp); i++ )
{
printf("%d ", *(int *)list_data(elem_ptr) );
elem_ptr = list_next(elem_ptr);
}
printf("\n\n");
printf("here begin to destroy the list :\n");
//destroy the linked list
list_destroy(&list_exp);
return 0;
}
4 显示执行结果,如下图: