#include <stdio.h>
#include <stdlib.h>
//链表
//1. 定义数据类型
typedef int Data_t;
//2. 定义节点类型
typedef struct node_t
{
Data_t data; //数据域:存储数据本身的
struct node_t *next;//指针域:存储逻辑关系
}node_t;
//创建空链表
//返回值 失败返回 NULL
//成功 返回 链表头节点地址
node_t * create_link_list(void)
{
node_t *p = (node_t *)malloc(sizeof(node_t));
if(p) p->next = NULL; //空链表 头节点next=NULL
return p;
}
//链表插入节点
int insert_data(node_t *head, int index, Data_t data)
{
if(head == NULL) return -1;
//1. 创建新节点空间
node_t *q = (node_t *)malloc(sizeof(node_t));
if(q == NULL) return -2;
q->data = data;//存储data到q节点中
//2. p指针 找到index的前一个节点地址
node_t *p = head;
//移动p 指向index前一个节点位置 p 到最末尾仍然没有到index前一个位置
for(int i=0;i<index && p != NULL ; i++) p = p->next;
if( p == NULL )
{//p 到最末尾仍然没有到index前一个位置
printf("%d 位置 没有在链表上!\n",index);
return -3;
}
else
{//p找到index位置的前一个节点的地址
//3.将新节点插入到链表中
q->next = p->next;
p->next = q;
}
return 0;
}
//遍历链表
int show_link_list(node_t *head)
{
if(head == NULL ) return -1;
if(head->next == NULL)
{
printf("\n");
return 0;
}
node_t *p = head->next;
for( ; p != NULL ; p=p->next )
printf("%d ", p->data);
printf("\n");
}
//给定下标index删除该节点
int del_data(node_t *head, int index)
{
if(head == NULL || head->next == NULL ) return -1;
//1.找到index前一个节点地址p
node_t *p = head;
for( int i=0;i<index && p->next != NULL ; i++) p=p->next;
if(p->next == NULL)
{
printf("%d 节点没有在链表上,删除失败!\n",index);
return -2;
}
//2. 备份index节点地址 q
node_t *q = p->next;
//3. 链接index左右两边的节点
p->next = q->next;
//4. 释放节点q节点
free(q);
return 0;
}
//拼接两个链表
int connect_link_list(node_t *head1,node_t *head2)
{
if(head1 == NULL || head2 == NULL) return 0;
if(head2->next == NULL) return 0;
node_t *p = head1;
//找最后节点p
while(p->next != NULL) p = p->next;
//拼接2两个节点
p->next = head2->next;
//head2 设置为空表
head2->next = NULL;
return 0;
}
//链表翻转
int link_list_Reverse(node_t* head)
{
if(head ==NULL || head->next == NULL) return -1;
//1. 头节点 与 数据节点分离
node_t *p = head->next;
node_t *q; // 临时中转指针
head->next = NULL; //头 空链表
//2. 依次从身体中取出一个节点 头插发到链表
while(p != NULL)
{
//insert_data(head, 0, p->data); // 存在内存泄露
q = p; //备份p到q
p=p->next; //移动p
q->next = head->next; // 头部插入
head->next = q; //
}
return 0;
}
//1.修改下标位置的值
int change_data(node_t* head, int index , Data_t data)
{
if(head == NULL|| head->next == NULL) return -1;
//找到index位置节点指针p
node_t *p = head -> next;
for( int i = 0 ; i < index && p != NULL ; p=p->next, i++);
if(p == NULL)
{
printf("%d 节点不在链表上!\n",index);
return -2;
}
//改index节点的内容
p->data = data;
return 0;
}
//获取链表的长度
int get_len(node_t *head)
{
if(head == NULL) return -1;
// if(head->next == NULL) return 0;
node_t *p = head;
int cnt = 0;
for( ; p->next != NULL ; p=p->next, cnt ++);
return cnt;
}
//2. 给定data查询第一个data出现的节点地址和下标
int find_data(node_t *head, Data_t data, node_t **answer_addr)
{
if(head == NULL) return -1;
if(head->next == NULL) return -2;
node_t *p = head->next;
int cnt = 0;
for(; p != NULL && p->data != data ; p=p->next, cnt++);
if(p==NULL) return -3;
//answer_addr 为NULL表示调用者 不在乎节点地址
if(answer_addr ) *answer_addr = p;
return cnt;
}
//给定节点地址删除该节点
int del_data_byaddr(node_t *head, node_t* delp)
{
if(head == NULL || delp == NULL) return -1;
if(head ->next == NULL ) return -2;
node_t *p = head;
for(; p->next != NULL && p->next != delp ; p=p->next);
if(p->next == NULL)
{
printf("节点%p,未找到!\n",delp);
return -3;
}
p->next = delp->next;
free(delp);
return 0;
}
int main()
{
//创建一个链表
node_t *head = create_link_list();
if(head == NULL)
{
printf("创建失败!!\n");
return -1;
}
else
printf("创建成功 head=%p\n",head);
node_t *head2 = create_link_list();
if(head2 == NULL)
{
printf("创建失败!!\n");
return -1;
}
else
printf("创建成功 head2=%p\n",head2);
//插入数据到链表
insert_data(head, 0, 10);
insert_data(head, 1, 20);
insert_data(head, 1, 30);
insert_data(head, 1, 40);
show_link_list(head);
for(int i=1;i<10;i++) insert_data(head2,0,i);
show_link_list(head2);
connect_link_list(head,head2);
show_link_list(head);
show_link_list(head2);
link_list_Reverse(head);
show_link_list(head);
printf("head长度=%d\n",get_len(head));
printf("修改head[%d]的值为100!\n", get_len(head)-3);
change_data(head, get_len(head)-3, 100);
show_link_list(head);
printf("查找data节点地址和下标!\n");
node_t * np;
int ret = find_data(head, 100, &np);
if(ret < 0) printf("没有找到100!\n");
else
{
printf("找到100了,下标为[%d],np=%p, data=%d\n", ret, np, np->data);
del_data_byaddr(head,np);
show_link_list(head);
del_data_byaddr(head,np);
}
return 0;
}