DC - 14:头指针链表

本文详细介绍了头指针链表的基本概念及其实现细节,包括节点的插入、删除、逆序等核心操作,并针对每种操作中需要注意的关键点进行了总结。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天开始敲一个通讯录。。。看到要求之后脑子里只\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a

\n\n\n\n\n\n好在纠结了很长时间终于还是知道从哪儿开始了。虽然感觉这几天的学习效率还可以,但遇到题目还是\a\a\a\a。。。代码练习应该还是太少,各个部分的用法也应该还是掌握不到位。下面是头指针链表:

//头指针
#include <stdio.h>
#include <stdlib.h>

#define FALSE 0
#define TRUE  1


typedef int linkdata;


typedef struct _node 
{
	linkdata data;
	struct _node  *next;
}Node;



void Display (Node *h)     //只是显示head指向的链表,不需要对head进行操作,所以没必要传入
{                           //head的地址
	if (h == NULL)
		return ;
	
	int i;
	int count = 0;
    while(h)
	    {
			if (count++ % 4 == 0)
				printf("\n");
			 printf("%8d",h ->data);
			 h = h->next;
			
     	}
	printf ("\n");
	 
	
}



int Insert_head(Node **h, linkdata data)    //需要改变head的值,所以传入head的地址

{
	if (h == NULL)
	    return FALSE;
	
    Node* node = (Node *)malloc(sizeof (Node) / sizeof (char));
	if  (node == NULL)
		return FALSE;
	node ->data = data;
	node ->next = *h;
	*h          = node;
	
	return TRUE;
	
}

int Insert_last(Node **h, linkdata data)  //需要改变head的值,所以传入head的地址
{
		if (h == NULL)
	    return FALSE;
	
    Node* node = (Node *)malloc(sizeof (Node) / sizeof (char));
	if  (node == NULL)
		return FALSE;
	node ->data = data;
	node ->next = NULL;
	
	
	Node *tmp = *h;
	if (*h == NULL)
	    {
		    *h = node;
	    }
	else 
	{
		while (tmp ->next)
		{	
		    tmp = tmp ->next;
		}
		tmp ->next = node;
	}

	
	return TRUE;
}


int Insert_pos(Node **h, int pos, linkdata data)
{
	if (h == NULL || pos < 1)
	    return FALSE;
	
    Node* node = (Node *)malloc(sizeof (Node) / sizeof (char));
	if  (node == NULL)
		return FALSE;
    node ->data = data;
	
	if (*h == NULL)                         // 考虑空表
	{
		if (pos != 1)
		{
			printf ("当前表为空,插入错误\n");
			free (node);
			return FALSE;
		}                               //空表插在第一个是可以的
			node ->next = NULL;
			*h = node;
	}
	else
	{   

        if (pos == 1)                        //非空表对第一个操作需要改变头指针的指向
		{
			node ->next = *h;
			*h = node;
		}
		else
		{
			Node *tmp = *h;
		    int i;
		    for (i = 0; i < pos - 2; i++)
		    {
			    if (tmp == NULL)
			    break;
			    tmp = tmp ->next;  
				

		
		    }
	        if (tmp == NULL)  
			{
				
				printf ("插入越界\n");
				free(node);
				return FALSE;
			}
			node ->next = tmp ->next;
			tmp ->next  = node;

		}
	}
	
	return TRUE;
}



int Delete_data(Node **h, int pos)
{
    if (h ==NULL || pos < 1 || *h == NULL)    //空表在这儿判断
	{
		return FALSE;
	}
	Node* tmp = *h;
	

    if (pos == 1)
	{
		Node *p = tmp ;
		*h      = tmp ->next;
	     free(p);
	}
	else
	{
		int i;
		for (i = 0; i < pos - 2; i++)
		{
			
			if (tmp ->next == NULL)
			
			    break;
				tmp = tmp->next;
			
		
		}
	        if (tmp ->next == NULL)  
			{
				
				printf ("删除越界\n");
				return FALSE;
				
			}
			
			Node *p = tmp ->next;
			tmp ->next = p ->next;
			free(p);
			
			
	}
	return TRUE;
	
}




//逆序头指针表
int Reserve(Node **h)
{
	if (h == NULL || *h ==NULL || (*h) ->next == NULL)   //顺序不可变
		return FALSE;
	Node *pre = *h;
	Node *cur = (*h) ->next;
	Node *tmp;
	while (cur)
	{
	    tmp = cur ->next;
		cur ->next = pre;
		pre = cur;
		cur = tmp;
	}
	(*h) ->next = NULL;
	*h  = pre;
	
	return TRUE;
	    
		
}

int main()
{
	Node *head = NULL;
    int i;
	for (i = 0; i < 10; i++)
	{
        Insert_head(&head, i);
	}
	printf("插入后的数据为:\n");
	Display(head);
	
	
	/*for (i = 0; i < 10; i++)
	{
		Insert_last(&head, i);
	}
	Display(head);
	*/
	

	Insert_pos(&head, 8, 10000);
	printf("选择pos插入后的数据:\n");
	Display(head);
	
	
	Delete_data(&head, 11);
	printf ("数据:\n");
	Display(head);
	
	Reserve(&head);
	printf("逆序后的数据为:\n");
	Display(head);
	return 0;
	
}
总体而言,头指针链表比上篇顺序表难了很多。先总结如下:

(1)头指针链表内存是不连续的,但每个节点都只有!!只有!!只有!!下一个节点的地址,所以断开链表之前一定要保存或者有另外的指向它,否则会造成内存泄漏。

(2)对于头指针的链表操作需要考虑的情况很多,不能遗漏任何一种情况,否则程序会出现异常,涉及到头指针的操作,请传入头指针的地址,对头指针的指向进行改变,否则会造成内存泄漏。

(3)对于for循环中的pos减1还是减2的问题请画图进行模拟,对于任意的pos的操作,我们应该循环到前一个值,因为链表保存了下一个地址,既然是对pos的操作,前继后继都是需要的,所以循环应该在pos的前一个点停下来。

(4)链表的  (->next)是个好东西,在各种判断,各种找地址的都很巧妙。

(5)逆序头指针表是需要三个指针,四步骤,从第一第二两个节点分别存值->逆序,->前一个后移,->后一个指向未逆序的节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值