链表的一种写法(部分通讯录功能)

这篇博客介绍了如何使用C语言实现链表的各种操作,包括创建链表、在头部、尾部和中间插入节点、删除节点、查找节点以及反转链表。代码包含多个辅助函数,便于理解和实践链表的基本操作。
摘要由CSDN通过智能技术生成
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

struct node//定义node结构体
{
    int num;
/*	char name[20];
	char sex;
	int age;
	char addr[200];
    int tel;*/

	struct node * next;//定义指针域
};

typedef struct node Node;//令struct node = Node
//typedef struct node * Link;
typedef Node * Link;

void create_link(Link * head)//创建一个链表(头指针为空)
{
	*head = NULL;
}

void display(Link head)//输出函数
{
	Link p;//定义一个结构体指针p

	p = head;//这步是因为头指针head不可以移动,所以需要重新定义一个可以移动的指针p

	if(NULL == head)//如果头指针为空就代表这个链表为空
	{
		printf("Link is empty!\n");
		return;
	}

	while(NULL != p) //当p不等于空,执行循环(尾结点指针值为NULL)
	{
		printf("%d\n",p->num);//输出p指向的元素(在这里是num,因为在结构体中知定义了num)

		p = p->next;//p指向下一个链表中的下一个地址
	}
}

void is_malloc_ok(Link new_node)//判断分配动态存储空间是否成功的函数
{
	if(NULL == new_node)//判断指针new_node是否指向0
	{
		printf("malloc error!\n");
		exit(-1);//exit里的参数是自己拟定的,用于标志这系统的非正常退出,因为此函数是在分配空间失败后才会执行的
	}
}

void create_node(Link * new_node)//动态存储空间分配函数
{
	*new_node = (Link) malloc(sizeof(Node));//创建一个新的结点,malloc按结构体大小分配空间,强制转换成链表结构体类型

	is_malloc_ok(*new_node);//调用判断动态存储空间是否分配成功函数
}

void insert_node_head(Link *head,Link new_node)//头插函数
{
    new_node->next = *head;//新的指针域指向原来的头
    *head = new_node;//令头指针指向新的结点
}

void release_link(Link * head)//释放内存函数
{
	Link p;//定义链表结构体指针p

	p = *head;//头指针指向p

	while(NULL != p)//当p不等于NULL时执行循环
	{
		*head = (*head)->next;//头指针移向下一个链表中下一个地址
		free(p);//释放p
		p = *head;//就相当于p指针跟着头指针走,头指针走到哪就释放哪
	}
}

void insert_node_tail(Link * head,Link new_node)//尾插函数
{
	Link p;

	p = *head;//跟上面一样

	if(NULL == *head)//链表为空时执行程序
	{
		*head = new_node;//将新的结点当成头
		new_node->next = NULL;//新的结点的指针域为空(因为本来一个都没有,尾插之后就只有原来的一个)
	}
	else
	{
		while(NULL != p->next)//当指针域不为空时执行此循环
		{
            p = p->next;//p指向链表中的下一个地址
		}

		p->next = new_node;//链表不为空时,p的指针域为新的结点
		new_node->next = NULL;//新的结点为尾结点(因为尾结点的指针域为NULL)
	}
}

void insert_node_mid_front(Link * head,Link new_node,int loc)//中间插入函数(在指定位置前面插入)
{
	Link p,q;//定义指针pq

	p = q = *head;//头指针的内容为p q

	if(NULL == *head)//空链表
	{
		*head = new_node;//头指针为新的结点
		new_node->next = NULL;//新的结点为尾结点
	}
	else if((*head)->num == loc)//判断头指针指向的元素的位置,如果是指定位置运行
	{
        new_node->next = *head;//新结点的指针域为头指针
		*head = new_node;//新的结点就等于头指针
	}
	else
	{
	//	while(p->num != loc && p != NULL) //??
	    while(p != NULL && p->num != loc)//当p指向的值域不为空且p没有达到指定位置时
		{
			q = p;
			p = p->next;//定义的q紧紧的跟在p的后面差一个地址
		}
        
    //    if(NULL == p) //如果p指到尾指针了
	//	{
      //      q->next = new_node;//q的指针域为新的结点
	//	    new_node->next = NULL;//新的结点为尾结点
	//	}
	//	else //p没有指到尾指针就到了指定位置
	//	{
            q->next = new_node;//q的指针域为新的结点
			new_node->next = p;//新的结点的指针域为p
	//	}(想理解这里自己要画图)
	}
}

void insert_node_mid_sort(Link * head, Link new_node)//中间插入函数
{
	Link p,q;

	p = q = *head;

	if(NULL == *head)
	{
		*head = new_node;
		new_node->next = NULL;
	}  //上面的都跟之前的一样
	else if((*head)->num > new_node->num)//如果头指针指向的元素大于新的结点指向的元素
	{
		new_node->next = *head;//新的结点的的指针域为头指针 
		*head = new_node;//新的结点的值域为头指针的值(交换功能)
	}
	else
	{
		while(p != NULL && p->num < new_node->num)//当p没有指到尾指针,且p指向的值小于新的结点的值
		{
			q = p;
			p = p->next;//跟上面一样
		}

		q->next = new_node;
		new_node->next = p;//p q交换
	}
}

void delete_node(Link * head,int num_del)//删除函数
{
	Link p, q;

	p = q = *head;

	if(NULL == *head)
	{
		printf("Link is empty!\n");
		return;//一样
	}
	else if((*head)->num == num_del)//判断头指针的数值是否等于要删除的数值
	{
		*head = (*head)->next ;//头指针的指针域为头指针(原来头指针的后面的一个元素为头元素)
		free(p);
		return;
	}
	else//头指针的数值不等于原来要删除的数值
	{
        while(NULL != p && p->num != num_del)//当p不为空且p没有指向要删除的数时
		{
			q = p;
			p = p->next;//q跟着p移动
		}

		if(NULL == p)//如果p移动到等于空的时候
		{
			printf("no such node!\n");//输出没找到
		}
		else//找到了
		{
            q->next = p->next;//令p的指针域等于q的指针域
			free(p);
		}
	}
}

Link search_node(Link head,int num_serch)//查找函数
{
	Link p;

	p = head;

	if(NULL == head)//空链表
	{
		printf("Link is empty!\n");
        return NULL;
	}
	else
	{
       while( p != NULL && p->num != num_serch)//p不为空,p没找到
	   {
		   p = p->next;下一个
	   }

       if(NULL == p)//p为空
	   {
		   return NULL;
	   }
	   else
	   {
		   return p;
	   }
	}
}

int main()
{
	//struct node * head;
    Link head = NULL;//定义一个空头指针
	Link new_node = NULL;//定义一个空结点
	int i;
	int loc;
	int num_del;
	int num_serch;
	Link p_serch;

	create_link(&head);//创建链表函数声明

	srand((unsigned)time(NULL));//产生随机数函数声明

	for(i = 0; i < 10;i++)
	{
	   // new_node = (Link)malloc(sizeof(Node));
	   create_node(&new_node);
       // new_node->num = i + 1;
	   new_node->num = rand() % 100;
        //scanf("%d",&new_node->num);
        
		//insert_node_head(&head,new_node);
	   //insert_node_tail(&head,new_node);
	    insert_node_mid_sort(&head,new_node);
	}
	
	display(head);
#if 0
	printf("\n\n");

    create_node(&new_node);
	new_node->num = 100;

	printf("please input loc:\n");
	scanf("%d",&loc);

	insert_node_mid_front(&head,new_node,loc);

	display(head);


	printf("please input num to delete:\n");
	scanf("%d",&num_del);
	printf("\n\n");

	delete_node(&head,num_del);
	display(head);
#endif
    
	printf("please input num to search:\n");
	scanf("%d",&num_serch);

    p_serch = search_node(head,num_serch);

	if(NULL == p_serch)
	{
		printf("no such node!\n");
	}
	else
	{
		printf("%d\n",p_serch->num);
	}

	release_link(&head);

	display(head);

    return 0;
}

注释掉main函数的部分即可运行不同的内容。

代码的大概内容:

struct node //定义node结构体

typedef struct node Node//
typedef Node *Link//

各种功能:
void create_link(Link *head)//
void display(Link head)//
void is_malloc_ok(Link new_node)//
void create_node(Link *new_node)//
void insert_node_head(Link *head, Link new_node)//
void release_link(Link *head)//
vodi insert_node_tail(Link *head,Link new_node)//
void insert_node_mid_front(Link *head,Link new_node,int loc)//
void insert_node_mid_sort(Link *head,Link new_node)//
void delete_node(Link *head,int num_del)//
Link search_node(Link head,int num_serch)//
Void reverse_link(Link *head)//

Int main()//主函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值