#define OK 1
#define ERROR 0
typedef int Status;
typedef struct
{
ElemType data;
struct Node *next;
} Node;
typedef struct Node *LinkList; // 定义单链表
// 获取单链表的长度
Status GetElem(LinkList L, int i, ElemType *e)
{
in j; // 用于记录当前位置
LinkList p; // 用于指向当前位置
p = L->next; // p指向第一个结点
j = 1; // j初始化为1
while (p && j < i) // 当p不为空且j小于i时
{
p = p->next; // p后移一个结点
j++; // j加1
}
if (!p || j > i) // 当p为空或者j大于i时
return ERROR; // 返回错误
*e = p->data; // 将p的值赋给e
return OK; // 返回OK
}
// 在单链表中插入元素
Status ListInsert(LinkList *L, int i, ELemType e)
{
int j; // 用于记录当前位置
LinkList p, s; // p指向当前结点,s指向新结点
p = *L; // p指向第一个结点
j = 1; // j初始化为1
while (p && j < i) // 当p不为空且j小于i时
{
p = p->next; // p后移一个结点
j++; // j加1
}
if (!p || j > i) // 当p为空或者j大于i时
return ERROR; // 返回错误
s = (LinkList)malloc(sizeof(Node)); // 分配空间
s->data = e; // 将e赋给新结点
s->next = p->next; // 将新结点插入到p的后面
p->next = s; // 将p的后继指向新结点
return OK; // 返回OK
}
// 删除单链表中的第i个元素
Status ListDelete(LinkList *L, int i, ElemType *e)
{
int j; // 用于记录当前位置
LinkList p, q; // p指向当前结点,s指向待删除结点
p = *L; // p指向第一个结点
j = 1; // j初始化为1
while (p->next && j < i) //遍历寻找第i个元素
{
p = p->next; // p后移一个结点
j++; // j加1
}
if (!(p->next) || j > i) // 当p为空或者j大于i时
return ERROR; // 返回错误
q = p->next; // q指向待删除结点
p->next = q->next; // 将q的后继指向p的后继
*e = q->data; // 将q的值赋给e
free(q); // 释放q,free函数的作用是释放内存
return OK; // 返回OK
}
/*
插入和删除算法都是由2部分组成,第一部分就是查找第i个元素,第二部分就是插入或删除元素。
对于插入或删除数据越频繁的操作,单链表比起顺序存储来说,单链表的优势是很明显的。
*/
单链表与结构与顺序结构的优缺点:
①存储分配的方式不同,顺序存储结构用一段连续存储单元一次存储线性表的数据元素,单链表则采用链式存储结构,用一组任意的存储单元存放线性表的元素。
②时间性能:查找:顺序存储结构:O(1),单链表O(n),
插入和删除:顺序存储结构需要平均移动表长一半的元素,时间复杂度为O(n);单链表在找出位置的指针后,插入和删除时间复杂度仅为O(1)
③空间性能:顺序存储结构需要预分配存储空间,分大了就浪费,分小了,就容易发生溢出;单链表不需要分配空间,只要有就分配,元素个数也不收限制。