c语言链表
一、单链表(不带头结点的单向不循环链表)
1. 链表的特点
- n个节点离散分配
- 每一个节点之间通过指针相连
- 每一个节点有一个前驱节点和一个后继节点
- 首节点没有前驱节点,尾节点没有后继节点
【定义一个简单的结构体】
typedef struct link{
int data;//定义数据域
struct link *next;//定义指针域,存储直接后继节点信息
}Link;
- 数据域的内容可以自己来指定,指针域用于存放下一个节点的地址
2. 创建链表前须知
- 首节点:存放第一个有效数据的节点
- 头节点:在单链表的第一个节点之前附设一个节点,没有直接前驱,头节点的数据域可以不存储任何信息,指针域指向第一个节点的地址。头节点的作用是使所有链表的头指针非空。
- 头指针:指向头节点的指针
- 尾节点:存放最后一个有效数据的节点
- 尾指针:指向尾节点的指针
3. 创建单链表
- 代码
Link *create(Link *phead, int size)
{
phead = (Link *)malloc(sizeof(Link));//头节点没有值
Link *end = phead;//定义尾指针指向头指针
end->next = NULL;//尾指针指向NULL
Link *p = NULL;//定义新节点的指针
int i = 0;
int data;
while(i<size)
{
scanf("%d",&data);
p = (Link *)malloc(sizeof(Link));//创建普通结点
p->data = data;
end->next = p;
p->next = NULL;
end = p;
i++;
}
return phead;
}
- 图解
4. 增加结点
- 代码
Link *add_Node(Link *phead, int size, int value)
{
Link *p = phead->next;
Link *Node = (Link *)malloc(sizeof(Link));//给新结点分配空间
int i = 0;
while(p!=NULL)
{
i++;
if(i == size)
{
Node->data = value;//赋值给新结点
Node->next = p->next;//把新结点的指针指向当前结点的下一个结点
p->next = Node;//将当前结点的指针指向新结点
break;
}
p = p->next;
}
return phead;
}
- 图解
5. 删除结点
- 代码
Link *delete_Node(Link *phead, int size)
{
Link *p = phead->next;
int i = 0;
while(p!=NULL)
{
i++;
if(i == size)
{
p->next = p->next->next;//没有释放空间
free(p);//回去做验证
break;
}
p = p->next;
}
return phead;
}
- 图解
6. 查询结点
- 代码
Link *research_Node(Link *phead, int size)
{
Link *p = phead->next;
int i = 0;
while(p!=NULL)
{
i++;
if(i == size)
{
printf("第%d个位置的值是: %d\n\n",i,p->data);
break;
}
p = p->next;
}
return phead;
}
- 图解
7. 修改结点
- 代码
Link *transfor_Node(Link *phead, int size, int value)
{
Link *p = phead->next;
int i = 0;
while(p!=NULL)
{
i++;
if(i == size)
{
p->data = value;//将当前结点的指针指向新结点
break;
}
p = p->next;
}
return phead;
}
- 图解
7. 排序
- 代码
//链表的排序--冒泡排序法 --按照自己的方式--时间复杂度为:f(n) = n*n
Link *Sort_List(Link* pHead )
{
Link *p = pHead->next;
Link *p1 = NULL;
while(p!=NULL)
{
p1=pHead;
while(p1->next!=NULL)
{
if(p1->next->data > p1->data)
{
int data;
data = p1->next->data;
p1->next->data = p1->data;
p1->data = data;
}
p1 = p1->next;
}
p = p->next;
}
return pHead;
}
- 图解
8.遍历链表
- 代码
void print(Link *head)
{
Link *p = head->next;
while(p!=NULL)//回去验证一下这个地方
{
printf("%d ",p->data);
p=p->next;
}
printf("\n");
}
- 图解
二、单循环链表
- 循环链表是一种头尾相接的链表(就是最后一个结点的指针指向第一个节点)
- 优点:从表中任意一节点出发都可以找到表中其他节点
- 注意:循环链表中没有NULL指针,故遍历链表时,其终止条件是判断是不是等于头指针。
【1. 循环链表的创建】
- 结构体创建
typedef struct link{
int data;//定义数据域
struct link *next;//定义指针域
}Link;
- 循环链表创建
Link *create(Link *phead, int size)
{
phead = (Link *)malloc(sizeof(Link));//头节点没有值
Link *p = phead;//指向头指针
p->next = p;
Link *p1 = NULL;//定义新节点的指针
int i = 0;
int data;
while(i<size)
{
scanf("%d",&data);
p1 = (Link *)malloc(sizeof(Link));//创建新节点、分配新的空间
p1->data = data;
p->next = p1;
p1->next = phead;
p = p1;
i++;
}
return phead;
}