#include <stdio.h>
#include <stdlib.h>
//结构体,为链表做准备
typedef struct A{
int num;
struct A *next;
} AA;
/*
*创建链表函数
*/
AA *create(int n){
int i;
AA *head, *node, *end; //定义头结点,普通节点,尾节点
head = (AA *)malloc(sizeof(AA)); //给头节点分配地址
end = head; //一开始为空链表则头尾节点一样。
for(i = 0; i < n;i++){
node = (AA *)malloc(sizeof(AA)); //为普通节点开辟内存
printf("NUM:\n");
scanf("%d",&node->num);
end->next = node;
end = node;
//这两个顺序不能反,要调一调上一个节点让其连接新建的节点,新建节点时,head不动,node先去开辟一个新节点,
//此时end还没动还在上一个节点,开辟好新节点了end所在的节点(即是新开节点的上一个节点)的指针是没有指向任何东西的,
//此时就要让上一个节点指向新开的节点,而end刚好在上一个节点中,就让end->next = node即可让上一个节点指向新节点,
//连接起来后又因为end是尾节点,要跟着node走,所以让end = node即可让end来到最后一个节点上
}
end->next = NULL; //为了安全,最后一个节点赋空,至此,已完成链表创建.
return head; //返回头结点
}
/*
*获取链表指定节点
*/
AA *get_linked_value(AA *head,int n){ //n为第几个节点
//获取头指针
AA *h = head;
int i = 1;
//要判断n是否大于n来返回报错信息,第一个节点是头节点不能被改
if(n < 1 || n > get_linked_len(h))
goto ERROR; //跳去报错区域执行报错
//用循环获取到指定节点
for(i;i <= n;i++){
//从头节点开始,一次次获取下一个节点来拿到指定位置的节点
h = h->next;
}
return h;
//报错区域
ERROR:
printf("该节点不存在");
}
/*
*改变链表指定节点的值
*/
void change_linked_value(AA *head,int n,int value){
//先获取指定节点,调用已经写好的函数
AA *node = get_linked_value(head,n);
//改变值
node->num = value;
}
/*
*增加链表的节点(在末尾添加)
*/
AA *add_linked_value(AA *head,int value){
AA *node = head;
AA *end = NULL;
//用循环,获取到最后一个节点
while(!(node->next == NULL)){
node = node->next;
}
//新增一个节点,用malloc为节点开辟一块内存
end = (AA *)malloc(sizeof(AA));
//创建好一个节点立刻为其指针赋NULL
end->next = NULL;
end->num = value;
//之前的最后一个节点(即现在的倒数第二个节点)的指针指向end
node->next = end;
//返回尾节点
return end;
}
/*
*在指定位置插入新的节点
*/
AA *insert_linked_value(AA *head,int n,int value){
AA *newNode,*node,*beforeN; //定义新节点,原来位置的节点和原来位置的上一个节点
AA *h = head;
//用之前写好的函数获取到指定位置的节点及其上一个节点,把新节点的指针指向原来位置的节点
//,而上一个节点把指针指向新节点即可
node = get_linked_value(h,n);
beforeN = get_linked_value(h,n-1);
//为新节点开辟一块内存空间
newNode = (AA *)malloc(sizeof(AA));
//立刻为新节点的指针赋值,为原来位置的节点
newNode->next = node;
newNode->num = value;
//把原来位置的上一个节点的指针指向新节点
beforeN->next = newNode;
return newNode;
}
/*
*删除指定位置的节点
*/
void delete_linked_value(AA *head,int n){
AA *h = head;
AA *beforeH = NULL;
//获取该节点的以及其上一个节点
beforeH = get_linked_value(h,n-1);
h = get_linked_value(h,n);
判断是否要删除尾节点
if(n == get_linked_len(h)){
//删除尾节点,把尾节点的上一个节点的指针设为NULL
beforeH->next = NULL;
//free掉尾节点
free(h);
}
//删除节点,先把上一个节点的指针指向要删除的节点的下一个节点
beforeH->next = h->next;
//把要删除的节点free掉
free(h);
}
/*
*输出链表内容函数
*/
void linked_list(AA *head){
//输出链表
while(!(head->next == NULL)){
//要先把head调至第二个节点,因为第一个节点head没有任何数据,只是一个头节点,只有指针存的是第二个节点的地址
head = head->next;
printf("%d\n",head->num);
}
}
/*
*获取链表的节点个数
*/
int get_linked_len(AA *head){
AA *h = head;
int len = 0;
//循环来统计个数
while(!(h->next == NULL)){
h = h->next;
len++;
}
return len;
}
/*
*主函数
*/
void main(){
AA *head;
AA *node;
int n;
printf("n:\n");
scanf("%d",&n);
//创建链表
head = create(n);
//获取第2个节点的值
node = get_linked_value(head,2);
printf("%d\n",node->num);
//改变第2个节点的值
change_linked_value(head,2,222);
//删除第3个节点
delete_linked_value(head,3);
//插入一个节点
insert_linked_value(head,3,888);
//新增一个节点
add_linked_value(head,222);
//输出链表内容
linked_list(head);
getchar();
getchar();
}
图形解释:
1、创建链表
2、新增节点
3、插入节点
4、删除节点