Part 1.完成单向链表,并完成下面功能
1.单链表节点创建
链表是物理空间上不连续的一个结构,需要创建一个next作为指向下一个节点的指针,所以需要建立一个结构体包含数据域,next指针域,记录长度的数据域。因为长度只有头节点可以储存,所以需要建立一个联合体,head访问len,普通节点访问data。

cs
typedef struct Node
{
//结构体嵌套共用体
union
{
//普通节点数据域
datatype data;
//头结点数据域:链表长度
int len;
};
//指针域
struct Node *next;
}*linklist;
linklist create_node(int flag)
{
linklist s = (linklist)malloc(sizeof(struct Node));
if(NULL == s)
{
return NULL;
}
if(flag == 1)//头节点
s->len = 0;
else if(flag == 0)//普通节点
s->data = 0;
s->next = NULL;
return s;
}
2.单链表的头插
链表的插入需要检查链表是否创建完成,因为每个节点空间不连续,所以得单独创建。
头插只需要将需要插入的数据的next指向原第一个节点,再将头节点的next指向新节点即可。
cs
int head_insert(linklist head,datatype element)
{
if(NULL == head)//检查链表是否创建完成
return Faulse;
linklist s = create_node(0);//创建普通数据节点
if(NULL == s)
return Faulse;
s->data = element;
s->next = head->next;
head->next = s;
head->len++;
return Success;
}
3.单链表头删
需要将头节点指向第二个节点(p->next->next)即可,然后释放p->第一个节点
cs
int head_delete(linklist head)
{
if(NULL == head || head->len == 0)
return Faulse;
linklist del = head->next;
head->next = del->next;
free(del);
del = NULL;
head->len--;
return Success;
}
4.单链表的尾插
因为链表的最后一个节点都是指向NULL,所以只需要循环寻找最后一个节点,然后将最后一个节点指向新节点,新节点指向NULL即可
cs
int rear_insert(linklist head,datatype element)
{
if(NULL == head)
return Faulse;
linklist s = create_node(0);
if(NULL == s)
return Faulse;
s->data = element;
linklist p = head;
while(p->next != NULL)//循环寻找原最后节点
p=p->next;
p->next = s;
head->len++;
return Success;
}
5.单链表遍历
只需要循环输出p->data(数据域),然后p = p->next往下一个节点即可完成循环输出遍历
cs
int output(linklist head)
{
if(NULL == head)
return Faulse;
linklist p = head->next;
while(p != NULL)
{
printf("%d\t",p->data);
p=p->next;
}
printf("\n");
}
6.单链表按位置查找
需要判断给的值是否大于长度,然后循环从0到输入的位置,进行p=p->next下移,然后输出即可
cs
int position_select(linklist head,int position)
{
if(NULL == head || position > head->len+1 || position < 1)
return Faulse;
linklist p = head;
for(int i = 0; i < position; i++)
p = p->next;
printf("%d个位置是:%d\n",position,p->data);
return Success;
}
7.单链表按位置删除
和按位置查找一样,然后循环从0到输入的位置,进行p=p->next下移,然后使用尾删即可。
cs
int position_delete(linklist head,int position)
{
if(NULL == head || position > head->len+1 || position < 1)
return Faulse;
linklist p = head;
for(int i = 0; i < position-1; i++)
p=p->next;
linklist del = p->next;
p->next = del->next;
free(del);
head->len--;
return Success;
}
8.单链表按位置修改
和按位置查找一样,然后循环从0到输入的位置,进行p=p->next下移,然后修改p->data修改数据域即可。
cs
int position_change(linklist head,int position,datatype element)
{
if(NULL == head || position > head->len+1 || position < 1)
return Faulse;
linklist p = head;
for(int i = 0; i < position; i++)
p = p->next;
p->data = element;
return Success;
}
9.单链表按元素查找
通过for循环,从第一个节点到最后一个节点进行和输入值对比,在每次循环记得将p下移,找到输入值的时候,输出i即可,既是第i个节点。
cs
int element_select(linklist head,datatype element)
{
if(NULL == head)
return Faulse;
linklist p = head;
for(int i = 1; i <= head->len; i++)
{
p = p->next;
if(p->data == element)
return i;
else if(i == head->len+1)
printf("没有这个数\n");
}
}
10.单链表按元素修改
和按元素查找相似,从第一个节点到最后一个节点进行和输入值对比,然后找到后,将data数据域修改即可。
cs
int element_change(linklist head,datatype element,datatype changeelement)
{
if(NULL == head)
return Faulse;
linklist p = head;
for(int i = 1; i <= head->len; i++)
{
p = p->next;
if(p->data == element)
p->data = changeelement;
else if(i == head->len+1)
printf("没有这个数\n");
}
return Success;
}
11.单链表按元素删除
可以直接在函数里调用元素寻找函数,将返回的地址值,然后赋给按位置删除函数,删除即可。
cs
int element_delete(linklist head,datatype element)
{
if(NULL == head)
return Faulse;
int i = element_select(head,element);
position_delete(head,i);
return Success;
}
12.单链表逆置
cs
int reverse(linklist head)
{
if(NULL == head)
return Faulse;
linklist p = head->next;
head->next = NULL;
for(int i = 0; i < head->len; i++)
{
linklist temp = p;
p = p->next;
temp->next = head->next;
head->next = temp;
}
return Success;
}
13.单链表排序
运用了冒泡排序的基础模板,只不过内部的交换变成了节点之间的互相连接。交换原理是:1.定义一个s指向p->next(记录第二个节点)
2.p就能指向p->next->next(第一个节点指向第三个节点)
3.s->next = p(将第二个节点指向第一个节点)
4.p的上一个节点需要指向第二个节点
按上面四步可以完成交换值,但是因为单项链表没办法调用上一个节点,所以需要定义p(原上一个节点),p->next(原p节点),s = p->next->next(原第二个节点),即每个节点往前移一个节点进行提前比较,换值即可。然后在每次换之后将p往下移(p = p->next)即可(因为链表没使用到循环的i和j,所以步长需要自己增加)。
cs
int sort(linklist head)
{
if(NULL == head || head->len <= 1)
return Faulse;
linklist p = head;
printf("%d\n",head->len);
for(int i = 1; i < head->len; i++)
{
p = head;
for(int j = 0; j < head->len-i; j++)
{
if(p->next->data > p->next->next->data)
{
linklist s = p->next->next;//交换
p->next->next = s->next;
s->next = p->next;
p->next = s;
p = p->next;//步增
}
else
p = p->next;
}
}
return Success;
}
14.单链表查找倒数第n个节点
寻找倒数第n个值,需要定义两个指针,指针之间相差n个节点距离,然后两个一起后移,当后面一个指针到末尾了,前一个指针就指向倒数第n个值了
cs
int rearnum_select(linklist head,int num)
{
if(NULL == head)
return Faulse;
linklist p = head;
linklist q = head;
for(int i = 0; i < num; i++)//令两个指针相隔n
{
q = q->next;
}
while(q != NULL)//一起后移,到底输出前一个指针
{
p = p->next;
q = q->next;
}
printf("倒数第%d个数是:%d\n",num,p->data);
}