c语言单向链表的简单程序,C语言-------实现一个简单的单向链表

#include

#include

struct node{

int num;

char name[20];

struct node* next; //指向下一个地址的指针

}; //声明一个链表,此时内存不分配内存

typedef struct node Node; //重命名,便于书写,太长了struct node

typedef struct node* Link;

//构造函数,实现传过来的头指针指向一个空的内容

void creat_node(Link *head) //形参为二级指针,操作的对象是指针变量的指针,这个概念我之前纠结了很久,很容易混.就单纯的理解为对变量的值进行操作,这个变量是指针{*head = NULL; //*head是指针的内容}

//头插,链表中节点的插入方式

void insert_head(Link *head,Link p) //函数操作的形参是头指针和新指针的地址,需要改变头指针的指向,所以调用的是二级指针{Link a;a = *head; if(a == NULL){a = p;p -> next = NULL;}else{p -> next = *head;// *head -> next = NULL;这句被注释掉了,这个是我当时犯的错,这样操作会使链表丢失*head = p;}}

//尾插

void insert_tail(Link *head,Link p) //原理同头插,尾插时注意新节点的next指针要指向NULL,在链表中循环时注意循环结束条件和循环体执行的操作

{

Link a;

a = *head;

if( *head == NULL ) //头指针指向空时,没有节点

{

*head = p;

p -> next = NULL;

}

else

{

//*head -> next = p; 这句犯错同上,链表会断掉

while(a -> next != NULL) //这个循环,是在链表中找到它的最后一位,把新节点连接上去

{

a = a -> next;

}

a -> next = p;

p -> next = NULL;

}

}

//释放链表指针的空间

void release_node(Link head) //释放空间不需要头指针的移动,形参调用head的一级指针,传head的指向地址,头指针的内容改变时,头指针的指向改变,效果就是头指针的移动

{

Link p; //定义一个指针,指向head,实现对链表的操作

p = head;

while(p != NULL)

{

free(p); //释放指针变量p指向的空间

p = p -> next; // p为变量,更新了p的值,效果是指针变量p现在指向p的下一个节点

}

}

//打印链表中的内容

void display_node(Link head) //对链表的操作,不需要移动head的位置,形参取head的一级指针

{

Link a; //定义一个新指针变量a,指向head的位置

a = head;

while(a != NULL) //打印节点内容,指针变量a指向下一个节点,实现后移的循环,直到a指向一个NULL

{

printf("num = %d name = %s\n",a -> num,a -> name);

a = a -> next;

}

}

//计算返回一个单向链表的长度

int length_node(Link head) //对链表的操作,不需要移动head的位置,形参取head的一级指针

{

Link p;

int i = 0; //记录节点个数

p = head;

while(p != NULL) //直到p指向的空间是NULL

{

i++; //i+1技术

p = p -> next; //p指向下一个节点

}

return i; //返回值i是int的,要声明函数的返回值

}

//查找链表中指定节点的内容

void check_node(Link head,int k) //对链表的操作,不需要移动head的位置,形参取head的一级指针,k为指定节点数

{

Link p;

p = head;

if(p == NULL)

printf("链表为空,无内容可查\n");

else

{

while(p != NULL) //找到链表中的指定节点打印出来

{

if(p -> num == k)

{

printf("name = %s\n",p -> name);

break; //打印完成后要记得退出循环

}

else

p = p -> next; //p指向p的后一位字节

}

}

}

//删除指定节点

void delete_node(Link head,int x) //对链表的操作,不需要移动head的位置,形参取head的一级指针,k为指定节点数

{

Link p,q;

p = head;

if(head == NULL)

{

printf("链表为空\n");

return ;

}

if(head -> next == NULL) //链表中只有一个节点

{

if(p -> num == x)

{

free(p);

p = NULL;

return;

}

else

{

printf("没有该节点\n");

return;

}

}

while(p -> num != x) //找到指定节点删除

{

q = p; //记录当前p指向的位置,p满足循环条件时,q指向p的前一个节点地址

p = p -> next;

}

q -> next = p -> next;

p -> next = NULL; //断开p指向的字节在连边中的连接顺序

free(p); //释放空间

}

//中间插, 新节点插到任意位置

void add_node(Link *head,Link m,int y) //需要讨论head的指向,取二级指针,新节点的指针,插入节点的位置

{

Link p,q;

p = *head;

while(p -> num != (y - 1)) //指针p停在要插入位置的前一个节点

{

p = p -> next;

}

q = p -> next;

p -> next = m;

m -> next = q;

m -> num = y; //完成指针的指向操作

}

//指针num变量重赋值,

void replay_num(Link head)

{

Link p;

p = head;

int i = 0;

while(p != NULL)

{

p -> num = i + 1;

p = p -> next;

i++;

}

}

//主函数

int main( )

{

Link head = NULL;//head指向NULL 防止野指针

Link p = NULL; //定义一个指针P指向NULL,防止野指针

int k,x,y = 0,i = 0;

Link m = NULL; //防止野指针

creat_node(&head); //head指向一个空

printf("请输入姓名:\n");

for(i = 0;i < 3;i++)

{

p = (Link)malloc(sizeof(Node)); //malloc()函数分配Node大小的空间,类型转换为Link型,指赋给p

if(p == NULL)//空间分配失败

{

printf("malloc error!\n");

exit(-1); //结束进程 文件包含stdlib.h

}

p -> num = i + 1;

scanf("%s",p -> name);

//insert_head(&head,p); //头插

insert_tail(&head,p); //尾插

}

display_node(head);

printf("链表长度:%d\n",length_node(head));

printf("请输入想要查询的节点:\n");

scanf("%d",&k);

check_node(head,k);

printf("请输入想要删除的节点:\n");

scanf("%d",&x);

delete_node(head,x);

display_node(head);

m = (Link)malloc(sizeof(Node)); //m指向一个新分配的空间

printf("请输入想要插入的节点内容:\n");

scanf("%s",m -> name);

printf("请输入想要插入的节点位置:\n");

scanf("%d",&y);

add_node(&head,m,y);

replay_num(head); //调用add_node()函数后把num的内容重新排序

display_node(head);

release_node(head); //释放函数要放在最后 所有操作结束后释放空间

return 0;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值