掌握单链表很容易,把下面的代码弄懂,敲几遍,全部记住,而且记清每一个细节。
首先,在List.h中声明单链表的ADT.我们把我们所需要的自定义类型啊,函数啊,都声明出来,但这里我们只是声明他们,而具体实现则是在List.c中进行。
/**
* @file List.h
* @brief 单链表的声明
* @details
* @author mrbourne@163.com
* @date 2014-5-19
*/
#ifndef _List_H
//先声明实现单链表时所需的类型和结构,包括一个节点结构体,元素类型,指向元素的指针类型(同样可以用来表示单链表本身和元素位置)
struct Node;
typedef int ElementType; //此处根据链表中元素类型的不同 可以修改
typedef struct Node *PtrToNode;
typedef PtrToNode List;
typedef PtrToNode Position;
//接下来声明一些常用的函数,一定要记住这些函数,因为这些函数都是最常用最基础的
List MakeEmpty(List L); //置空链表
int IsEmpty(List L); //判空链表
int IsLast(Position P,List L); //判断是否为表尾
Position Find(ElementType X,List L); //找出元素所在位置
void Delete(ElementType X,List L); //删除元素
Position FindPrevious(ElementType X,List L); //找到某元素的前驱
void Insert(ElementType X,List L,Position P); //插入一个元素
void DeleteList(List L); //删除链表
Position Header(List L); //返回头结点
Position First(List L); //返回第一个元素
Position Advance(Position P); //返回后一个位置
ElementType Retrieve(Position P); //获取位置P处的元素值
#endif // _List_H
声明完了以后,我们就要逐步实现这些单链表的ADT,实现的代码放在List.c中
具体实现代码如下:
/**
* @file List.h
* @brief 链表的实现部分
* @details
* @author mrbourne@163.com
* @date 2014-5-19
*/
#include <stdio.h>
#include <stdlib.h>
#include <List.h> //别忘了先把声明部分的头文件List.h包含进来
//实现节点结构体
struct Node
{
ElementType Element; //元素
Position Next; //指向下个元素的指针
};
//空链表返回true
int IsEmpty(List L)
{
return L->Next == NULL;
}
//当前位置是否为链表末尾
int IsLast(Position P, List L)
{
return P->Next == NULL;
}
//找到一个元素所在的位置
Position Find(ElementType X, List L)
{
Position P;
P = L->Next; //P初始化为a1
while(P != NULL && P->Element != X) //只要没到表尾,且当前节点中的元素不等于所给参数,就一直向后遍历
P = P->Next;
return P;
}
//找到某个元素的前驱
Position FindPrevious(ElementType X, List L)
{
Position P;
while(P->Next != NULL && P->Next->Element != X) //下一个元素没到表尾,且下一个元素不匹配,则继续遍历
P = P->Next;
return P;
}
//删除某个元素x
void Delete(ElementType X, List L)
{
Position P,TmpCell; //前驱和当前节点
P = FindPrevious(X,L);
if(!IsLast(P,L)) //成功找到了该元素的前驱,若IsLast成立,则表示没有找到前驱
{
TmpCell = P->Next;
P->Next = TmpCell->Next;
free(TmpCell);
}
}
//打印错误信息
void FatalError(char *str)
{
printf("%s
", str);
}
//在某个元素前插入一个元素
void Insert(ElementType X, List L, Position P)
{
Position NewCell;
NewCell = malloc(sizeof(struct Node)); //申请空间
if(NewCell == NULL)
FatalError("Out of space!!!");
NewCell->Element = X;
NewCell->Next = P->Next;
P->Next = NewCell;
}
//删除一个链表
void DeleteList(List L)
{
Position P,Tmp;
P = L->Next;
L->Next = NULL; //释放头结点
while(P != NULL) //需要用Tmp保存当前节点 因为在free(P)后 不能再对P引用进行P = P->Next
{
Tmp = P->Next;
free(P);
P = Tmp;
}
}
至此,我们已经基本实现一个单链表和其基础的操作。这里有几个例程并没有实现,不要着急,这里的单链表还不能供我们使用,有几个历程和后面我们实现栈和队列时大同小异,等学完栈和队列,我们再回来把剩下的几个例程补上,然后也像测试栈和队列一样,在主程序中来测试一下单链表。