目录
一般链表都要设置头节点,否则改变指针的指向要传二级指针,很麻烦。头节点即什么都不放的头,头节点的指针是不动的。
单链表特点:
* 头插,头删的时间复杂度是O(1)尽量用头,快
* 尾插,尾删的时间复杂度是O(n)
初始化:
一个数据域存数据,一个指针域存放下一个节点的地址。
typedef struct Node
{
int data;//数据域
struct Node* next;//后继指针
}Node,*List;
链表初始化:
void InitList(List plist)
{
assert(plist != NULL);
if (plist == NULL)
{
return;
}
plist->next = NULL;
}
求链表的长度:
从第一个存数据的节点plist->next,找到最后一个节点,count记录节点数
int GetLength(List plist)
{
assert(plist != NULL);
if (plist == NULL)
return -1;
Node* p = plist->next;
int count = 0;
while (p != NULL)
{
count++;
p = p->next;
}
if (count == 0)
printf("空");
return count;
}
插入:
1.头插法
开辟一个新节点p,将数据存入,从开头插入数据,注意要先把后面连上,再连前面,否则会丢失后面的链表。
bool Insert_head(List plist,int val)
{
assert(plist != NULL);
if (plist == NULL)
return false;
Node* p = (Node*)malloc(sizeof(Node));
assert(p != NULL);
p->data = val;
p->next = plist->next;//先绑后面
plist->next = p;
return true;
}
2.尾插法
比头插多一个找末尾的操作
bool Insert_tail(List plist, int val)
{
assert(plist != NULL);
if (plist == NULL)
return false;
Node* p = (Node*)malloc(sizeof(Node));//申请节点
assert(p != NULL);
p->data = val;//将数据放入新节点
Node* q = plist;//这个不能是next防止是空表
while (q->next!=NULL)
{
q = q->next; //找尾巴
}
p->next = q->next;//先绑后面
q->next = p;
return true;
}
3.在链表pos位置插入val
//插入数据,在plist链表的pos位置插入val;
bool Insert(List plist, int pos, int val)
{
assert(plist != NULL);
if (plist == NULL)
{
return false;
}
if (pos<0 || pos>GetLength(plist))
{
return false;
}
Node* p = (Node*)malloc(sizeof(Node));
assert(p != NULL);
p->data = val;
//找位置
Node* q = plist;
int i;
for (i = 0; i < pos; i++)
{
q = q->next;
}
p->next = q->next;
q->next = p;
return true;
}
查找:
在plist查找第一个key值,找到返回节点地址,没找到返回NULL
Node* Search(List plist, int key)
{
assert(plist != NULL);
if (plist == NULL)
return NULL;
if (IsEmpty(plist))
return NULL;
Node* p = plist->next;
while (p != NULL)
{
if (p->data == key)
return p;
else
p = p->next;
}
return NULL;
}
删除:
1.删除pos位置的值
用q记录位置,然后free掉它就是删除了。
bool DelPos(List plist, int pos)
{
assert(plist != NULL);
if (plist == NULL)
return false;
if (pos<0 || pos>=GetLength(plist))
return false;
Node* p=plist;
int i;
for (i = 0; i < pos; i++)
{
p = p->next;//找pos位置
}
Node* q = p->next;//删q
p->next = q->next;
return true;
free(q);
}
2.删除第一个val值
bool DelVal(List plist, int val)
{
Node* p = GetPrio(plist, val);
if (p == NULL)
return false;
Node* q = p->next;//前驱的next指向val的next
p->next = q->next;
free(q);
return true;
}
返回key前驱、后继的下标
//返回key的前驱下标,如果不存在返回NULL
Node* GetPrio(List plist, int key)
{
assert(plist != NULL);
if (plist == NULL)
return NULL;
for (Node* p = plist; p->next != NULL; p = p->next)
{
if (p->next->data == key)
return p;
}
return NULL;
}
//返回key的后继地址,如果不存在返回NULL;
Node* GetNext(List plist, int key)
{
assert(plist != NULL);
if (plist == NULL)
{
return NULL;
}
Node* p = Search(plist, key);
if (p == NULL)
{
return NULL;
}
return p->next;
}
输出
void Show(List plist)
{
assert(plist != NULL);
if (plist == NULL)
return;
Node* p = plist->next;
while (p != NULL)
{
printf("%d--", p->data);
p = p->next;
}
printf("\n");
}
销毁
void Destroy(List plist)
{
Node* p;
while (plist->next != NULL)
{
p = plist->next;
plist->next = p->next;
free(p);//总是删除第一个数据节点
}
}