单向链表,大致操作有插入,删除,遍历,查找,销毁,它存取方便,只要修改节点的指针域即可。只是查找时,每次都需要从第一个开始遍历查找。
第一个节点只有直接后继,最后一个节点只有直接前驱。
对于插入操作,有头插法,尾插法,任意插,这些我们在实际运用中都要考虑到。它的一优势就是节省空间,灵活。而顺序表就容易造成空间的浪费。插入删除操作还会造成大量数据的移动。
单链表其实我认为是一种更为实用的数据类型,它将各种类型封装起来,来解决生活工作中遇到的实际问题。
下面开始实战:
/* list.h 头文件的定义 */
#ifndef _LIST_H_
#define _LIST_H_
#include <assert.h>
typedef struct node
{
int data;
struct node *next;
}node_t;
node_t *list_insert_fornt(node_t *head,int data);
typedef void (*FUNC)(node_t *);
void list_for_each(node_t *head,FUNC f);
node_t *list_get_node(node_t *head,int index);
node_t *list_insert_at(node_t *head,int data,int index);
node_t *list_remove_at(node_t *head,int index);
node_t *list_find(node_t *head,int data,int *ret);
node_t *list_free(node_t *head,int data);
#endif /* _LIST_H_ */
/* list.c 接口的实现 */
#include "list.h"
#include <stdio.h>
node_t *list_insert_fornt(node_t *head,int data)
{
node_t *n = (node_t *)malloc(sizeof(node_t));
assert(n != NULL);
n->data = data;
n->next = NULL;
if(head == NULL)
head = n;
else
{
n->next = head;
head = n;
}
return head;
}
void *list_for_each(node_t *head,FUNC f)
{
while(head)
{
f(head);
head = head->next;
}
}
node_t *list_get_node(node_t *head,int index)
{
int j = 0;
while(head && j < index)
{
head = head->next;
j++;
}
if(j == index)
<span style="white-space:pre"> </span>return head;
return NULL; //return head;
}
node_t *list_insert_at(node_t *head,int data,int index)
{
if(index == 0)
return list_insert_front(head,data);
node_t *n = (node_t *)malloc(sizeof(node_t));
assert(n != NULL);
n->data = data;
n->next = NULL;
node_t *p = NULL;
p = list_get_node(head,index - 1);
if(p != NULL)
{
n->next = p-next;
p->next = n;
}
else
printf("insert error.\n");
return head;
}
node_t *list_remove_at(node_t *head,int index)
{
assert(index >= 0);
if(index == 0)
{
n = head;
free(n);
head = head->next;
}
node_t *p = NULL;
p = list_get_node(head,index -1);
if(p == NULL || p->next == NULL)
{
fprintf(stderr,"remove error.\n");
exit(EXIT_FAILURE);
}
n = p->next;
p->next = n->next;
return head;
}
node_t *list_find(node_t *head,int data,int *ret)
{
*ret = -1;
int i = 0;
while(head)
{
if(data == head->data)
{
*ret = i;
break;
}
head = head->next;
i++;
}
return head;
}
node_t *list_free(head,data)
{
node_t *tmp = head;
while(head)
{
head =head->next;
free(tmp);
tmp = head;
}
return head;
}
/* main.c 测试代码 */
#include "list.h"
#include <stdio.h>
void print_node(node_t *n)
{
printf("data = %d \n",n->data);
}
int main(void)
{
node_t *head = NULL;
head = list_insert_fornt(head,30);
head = list_inset_fornt(head,20);
head = list_insert_fornt(head,10);
list_for_each(head,print_node);
putchar('\n');
node_t *n = NULL;
n = list_get_node(head,1);
if(n != NULL)
printf("data = %d\n",n->data);
else
printf("not find node.\n");
head = list_insert_at(head,15,1);
list_for_each(head,print_node);
putchar('\n');
head = list_remove_at(head,2);
list_for_each(head,print_node);
putchar('\n');
node_t *n = NULL;
int ret = 0;
n = list_find(head,20,&ret);
if(n != NULL)
printf("data = %d index = %d \n",n->data,ret);
else
printf("not find.\n");
head =list_free(head,data);
assert(head == NULL);
return 0;
}
以下是运行示例:分别是插入,查找,任意插入,删除节点,找出节点,最后销毁链表。
(finish)