1.初始化
void InitList(List plist)
{
assert(plist!=NULL);
if(plist==NULL)
{
return;
}
//plist->data;//不使用
plist->next=NULL;
}
2.头插
bool Insert_head(List plist,int val)//时间复杂度为O(1)
{
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
p->next = plist->next;
plist->next = p;//p就指向malloc分配空间的地址(即sizeof里的东西)
/*
Node newnode;//1
newnode.data = val;//2
newnode.next = plist->next;//4 防止气球飞走( 防止内存泄漏)
plist->next = &newnode;//3
*/
return true;
}
3.尾插
bool Insert_tail(List plist,int val)//O(n)
{
Node *p = (Node *)malloc(sizeof(Node));
p->data = val;
Node *q;
for(q = plist;q->next!=NULL;q = q->next);//找尾巴
//将p插入在q之后
p->next = q->next;//p->next = NULL;
q->next = p;
return true;
}
4.查找
Node *Srearch(List plist,int key)
{
for(Node *p = plist->next;p!=NULL;p = p->next)
{
if(p->data == key)
{
return p;
}
}
return NULL;
}
5.删除 删除依赖于前驱
bool Delete(List plist,int key)
{
Node *p;//p是q的前驱
for(p = plist;p->next!=NULL;p = p->next)
{
if(p->next->data == key)
{
Node *q = p->next;//记录要删除的节点
p->next = q->next;
free(q);
return true;
}
}
return false;
}
6.获取数据节点个数(不包含头节点)
int GetLength(List plist)
{
int count = 0;
for(Node *p = plist->next;p!=NULL;p = p->next)//遍历所有数据节点
{
count++;
}
return count;
}
7.判断链表是否为空(不包含头节点)
bool IsEmpty(List plist)
{
return plist->next == NULL;
}
8.清除数据
void Clear(List plist)
{
Destroy(plist);
}
9.摧毁数据
(1)最简单的方法
void Destroy(List plist)
{
Node *p;
while(plist->next!=NULL)
//为什么用plist->next而不用plist?
//这个摧毁数据的方法是最简单的,只摧毁最前面的第一个数据,后面的挨个向前走,正如排队买饭,阿姨不动,而同学们打一份,走一个人
{
p = plist->next;
plist->next = p->next;
free(p);
}
}
(2)逐个摧毁
void Destroy(List plist)
{
Node *p = plist->next;
Node *q;
while(p!=NULL)
{
q = p->next;//q是p的后继
free(p);
p = q;
}
plist->next = NULL;
}10.打印
void Show(List plist)
{
for(Node *p = plist->next;p!=NULL;p = p->next)
{
printf("%d ",p->data);
}
printf("\n");
}
11.得到某一位置的元素
//第一数据节点的pos为0
bool GetElen(List plist,int pos,int *rtval)
{
if(pos<0 || pos>Getlength(plist))
{
return false;
}
int i = 0;
for(Node *p = plist->next;p!=NULL;p = p->next)
{
if(i == pos)
{
*rtval = p->data;
return true;
}
i++;
}
return false;
}
12.得到结点p的前驱
static Node *GetPri(List plist,Node *p)
{
for(Node *q = plist;q->next!=NULL;q = q->next)
{
if(q->next == p)
{
return q;
}
}
return NULL;
}
13.逆置
void Reverse(List plist)//考试的重点内容
{
if(plist == NULL || plist->next == NULL || plist->next->next == NULL)//分别是:这个链表不存在;只有一个头结点;只有一个数据元素
{
return;
}
//下面的时间复杂度为O(n),并且最好,利用头插的思想
Node *p = plist->next;
Node *q;
plist->next = NULL;//保证最后一个结点的next项为NULL
while(p!=NULL)
{
q = p->next;//q是p的后继,q要插到p后面
p->next = plist->next;//将结点p头插到链表中
plist->next = p;
p = q;//往下走
}
//因为q保存了后面的结点,所以将p与后面的结点断开没有关系,再与前面的plist相连
/*
//下面的时间复杂度为O(n) 向后转
Node *p = plist->next;
Node *q = p->next;
Node *s;
p->next = NULL;//保证最后一个结点的next项为NULL
while(q != NULL)//注意区分q和q->next的区别
{
s = q->next;
q->next = p;//反转
p = q;
q = s;
}
plist->next = p;将反转后的第一个结点与头结点相连
*/
/*
//下面方法的时间复杂度为O(n^2)
Node *p = plist->next;
Node *q;
int tmp;
for(Node *q = plist;q!=NULL;q = q->next);//注意这不是for循环嵌套
for(int i = 0;i<GetLength(plist)/2;i++)
{
tmp = p->data;
p->data = q->data;
q->data = tmp;
p = p->next;
q = GetPri(plist,q);
}
*/
}
14.链表里不再有重复的元素
void Unique(List plist)
{
Node *p;
Node *q;
for(p = plist->next;p!=NULL;p = p->next)
{
for(q = p;q->next!=NULL;q = q->next)
{
if(q->next->data == p->data)
{
Node *s = q->next;
q->next = s->next;
free(s);
}
}
}
}