链表
简介
链表是一种常用的数据结构,它和数组的最大不同在于链表是随机分布可扩展的,而数组是连续分布不可扩展的。因为链表强大的可扩展性,几乎所有的语言都有内置的标准链表库,比如java实现List<T>接口的类,C++STL中的list<typename T>等。
链表图示
链表说明
如图,链表中的每一项都是由两部分组成。第一部分是数据段,第二部分是指向下一项的指针。最后一项的指针为空表示什么都不指向。另外由于指针需要指向链表中的下一项,因此指针的类型是该结构体类型。
插入图示
插入说明
如图所示,链表的存储方式决定了链表的插入及其快捷与简单。只需要删除将插入位置的前一项的指针指向插入项,而插入项的指针指向后一项即可。一般链表的实现是把数据插入到末尾,但将数据插入到其他的位置也是非常快捷的。
删除图示
删除说明
如图所示,同插入一样,链表的存储方式也使得删除操作变得简单。只需要将指向待删除位置的指针指向删除位置的后一项,而删除项的指针置为空即可。
修改与查找
链表的修改与查找并不需要修改指针,所以相比于数组,并没有任何性能上的提升。相反链表丢失了数组的随机访问能力,在某些情况下反而不如数组。
附注
在插入与删除操作中由于不需要对后续元素的操作,所以时间复杂度位θ(1),远远优于数组。 而在修改与查找操作中需要对整个链表遍历来找出目标元素,所以时间复杂度为θ(N),和数组并无区别。
简单链表库
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
struct Node
{
int num;
};
typedef struct List
{
struct Node node;
struct List *next;
}type;
typedef type* List;
/*
*对目标列表进行初始化
*@plist : 目标列表
*/
void InitializeList(List * plist)
{
*plist = NULL;
}
/*
*对两个参数进行比较。
*@node1: 第一个参数
*@node2: 第二个参数
*@return: node1 > node2 -> 1, node1 < node2 -> -1, equal -> 0
*/
static int CompareNode(struct Node node1, struct Node node2)
{
if(node1.num > node2.num)
return 1;
if(node1.num < node2.num)
return -1;
return 0;
}
/*
*将数据添加到链表的结尾
*@plist: 目标链表
*@vnode: 待插入项
*@return: 是否成功添加
*/
bool AddList(List *plist, struct Node vnode)
{
List mlist = malloc(sizeof(type)); // C语言会进行自动转换,不需要强制转换。C++需要强制类型转换
if(mlist == NULL)
return false;
mlist -> node = vnode;
mlist -> next = NULL;
if(*plist == NULL) // 目标链表为空
{
*plist = mlist;
return true;
}
// 目标链表不为空
List tlist = *plist;
while(tlist -> next != NULL)
tlist = tlist -> next;
tlist -> next = mlist;
return true;
}
/*
*在链表中寻找目标项
*@plist: 目标链表
*@vnode: 目标项
*@return: 指向目标项的指针, 不存在则返回NULL
*/
List FindInList(List *plist, struct Node vnode)
{
if(*plist == NULL)
return NULL;
List tlist = *plist;
while(tlist)
{
if(CompareNode(tlist -> node, vnode) == 0)
return tlist;
tlist = tlist -> next;
}
return NULL;
}
/*
*将目标项插入到链表某个指定项的后面
*@plist: 目标链表
*@vnode: 指定项
*@aimNode: 待插入项
*@return: 是否成功插入
*/
bool InsertList(List *plist, struct Node vNode, struct Node aimNode)
{
if(*plist == NULL)
return false;
List tlist = FindInList(plist, vNode);
if(tlist == NULL)
return false;
List aimlist = malloc(sizeof(type));
if(aimlist == NULL)
return false;
aimlist -> node = aimNode;
aimlist -> next = tlist -> next;
tlist -> next = aimlist;
return true;
}
/*
*在指定链表中删除指定项
*@plist: 目标链表
*@vnode: 指定待删除项
*@return: 是否成功删除
*/
bool DeleteInList(List *plist, struct Node vnode)
{
if(*plist == NULL)
return false;
List tlist = FindInList(plist, vnode);
if(tlist == NULL)
return false;
List mlist = *plist;
while(mlist -> next != tlist)
mlist = mlist -> next;
mlist -> next = tlist -> next;
free(tlist);
return true;
}
/*
*统计在指定链表中元素的个数
*@plist: 目标链表
*@return: 元素的个数
*/
int CountList(List *plist)
{
int count = 0;
List tlist = *plist;
while(tlist != NULL)
{
++count;
tlist = tlist -> next;
}
return count;
}
/*
*替换链表中某个指定的元素
*@plist: 目标链表
*@vnode: 待替换元素
*@tnode: 替换元素
*@return: 操作是否成功
*/
bool ReplaceInList(List *plist, struct Node vnode, struct Node tnode)
{
if(*plist == NULL)
return false;
List tlist = FindInList(plist, vnode);
if(tlist == NULL)
return false;
tlist -> node = tnode;
return true;
}
/*
*清空链表中所有的元素
*@plist: 目标链表
*@return: 是否清空整个链表
@warning: 使用该函数后,整个链表都不可用。
*/
bool ClearAllList(List *plist)
{
if(*plist == NULL)
return true;
List tlist;
while(*plist)
{
tlist = (*plist) -> next;
free(*plist);
*plist = tlist;
}
return true;
}