链表的基本使用

链表是一种常见的数据结构,其特点主要有以下几个方面:

  1. 动态分配内存:链表不需要预先分配固定大小的内存空间,而是可以在需要时动态地分配和释放。这使得链表在处理大小可变的数据集时非常灵活。
  2. 非连续性存储:链表中的元素通过指针连接在一起,而不是像数组那样在内存中连续存储。因此,链表中的元素可以分散在内存的任何位置。
  3. 插入和删除操作的高效性:在链表的任何位置插入或删除元素都只需要修改相邻节点的指针,而不需要移动大量元素。这使得链表在插入和删除操作上的时间复杂度低,特别是在链表的开头或结尾操作时。
  4. 访问元素的不便性:虽然链表在插入和删除操作上表现出色,但在访问特定元素时却相对不便。为了访问链表中的某个元素,通常需要从头节点开始,沿着指针逐个遍历节点,直到找到目标元素。这使得链表在访问操作上的时间复杂度较高,特别是当链表较长时。
  5. 空间开销:链表中的每个节点除了存储数据元素外,还需要存储指向下一个节点的指针,这增加了链表的空间开销,特别是在存储小数据元素时。然而,这种开销通常是可以接受的,因为链表提供了更高的灵活性和更高效的插入和删除操作。
  6. 循环链表和双向链表:链表有多种类型,包括单向链表、双向链表和循环链表等。这些不同类型的链表具有不同的特点和用途。例如,双向链表允许向前和向后遍历节点,而循环链表则允许从从尾节点直接访问头节点。

以下是关于链表的简单使用:

//定义链表结构体
typedef struct _Node{
    int data;
    struct _Node* next;
}Node;

//创建一个新节点
Node* CreateNode(int data)
{
	Node *newNode = (Node *)malloc(sizeof(Node));
	if(newNode == NULL)
	{
		printf(memory allocation failed.\n);
		exit(1);
	}
	newNode->data = data;
	newNode->next = NULL;
	return newNode;
}

//在链表头部插入节点
void InsertAtHead(Node **head, int data)
{
	Node *newNode = CreateNode(data);
	newNode->next = *head;
	*head = newNode;
}

//在链表末尾插入节点
/* 1.检查头结点是否为空,如果为空,新节点成为链表的第一个节点,则头节点指针应该指向这个新节点 */
/* 2.遍历到链表的末尾:如果链表不为空,需要遍历整个链表找到最后一个节点 */
/* 3.更新尾节点的next指针:一旦找到了尾节点,就需要将其next指针指向新节点,这样新节点就成为了链表的最后一个节点 */
/* 4.确保新节点的next指针为NULL */
void InsertAtTail(Node **head, int data)
{
	Node *newNode = CreateNode(data);
	Node *temp = *head;
	if(temp == NULL)
	{
		temp = newNode;
		*head = temp;
	}
	else
	{
		while(temp->next != NULL)
		{
			temp = temp->next;
		}
		temp->next = newNode;
	}
}
//在链表的任意位置插入新节点
void InsertAtPos(Node **head, int data, int position)
{
    Node *prev = NULL;

    Node *newNode = CreateNode(data);

    /* 如果链表为空,或者插入位置为0,则新节点成为头节点 */
    if((*head == NULL) || (position == 0))
    {
        newNode->next = *head;
        *head = newNode;
    }
    else
    {
        /* 找到要插入位置的前一个节点 */
        prev = *head;
        for(int i = 0; prev != NULL && i < position - 1; i++)
        {
            prev = prev->next;
            if(prev == NULL)
            {
                return;
            }
        }
        /* 插入新节点 */
        newNode->next = prev->next;
        prev->next = newNode;
    }
}

//删除指定数据的节点
void DeleteNode(Node **head, int data)
{
	Node *temp = *head;
	Node *prev = NULL;
	/* 判断删除的节点是否为头节点 */
	if((temp != NULL) && (temp->data == data))
	{
	 	printf("删除的为头节点.\n");
		*head = temp->next;
		free(temp);
		temp = *head;
	}

	/* 查找要删除的节点,并记录前一个节点 */
    while(temp != NULL)
    {
        /* 如果没有找到要删除的节点,则移动到下一个节点 */
        if(temp->data != data)
        {
            prev = temp;
            temp = temp->next;
        }
        else /* 如果找到了要删除的节点 */
        {
            printf("已删除对应节点.\n");
            /* 更新前一个节点的next指针以跳过当前节点 */
            prev->next = temp->next;
            /* 释放当前节点的内存 */
            free(temp);
            /* 移动到下一个节点 */
            temp = prev->next;
        }
    }
}

//遍历链表并打印节点数据
void PrintList(Node *head)
{
	Node *temp = head;
	while(temp->next != NULL)
	{
		printf("%d ", temp->data);
		temp = temp->next;
	}
	printf("\n");
}

//释放链表内存
void FreeList(Node *head)
{
	Node *temp;
	whie(head != NULL)
	{
		temp = head;
		head = head->next;
		free(temp);
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值