【数据结构】 链表

链表的概念及结构

概念:基于数组的缺点,数据结构中诞生了新的结构就是 链表

当一组数据需要频繁的进行插入、删除操作时候,链表则是首选的数据结构

链表也属于 线性表

链表的组成

链表由结点组成

结点分为两部分:

  • 数据域,保存存储的数据元素

  • 指针域,指向下一个结点的地址

注:链表也属于线性表,拥有线性表的所有特点

结点的创建:

struct Node{
    int data;    //数据域
    struct Node *next;    //指针域
};

结点结构体示意图:

实现单向链表,能够存放整型数据,设计需求如下:

设计需求:
  1. 链表的初始化

  1. 获取链表长度

  1. 插入指定位置结点

  1. 遍历链表

  1. 删除指定位置结点

  1. 清空链表

  1. 释放链表

链表的初始化

链表初始化 核心代码:
typedef struct node
{
    int data;//数据域
    struct node* next; //指针域
}Node, *LinkList;  //Node是struct node的别名, LinkList 代表struct node*数据类型

//链表的初始化
LinkList creat_list()
{
    LinkList head  = (Node *)malloc(sizeof(Node));
    if (!head)
    {
        printf("内存分配失败\n");
        return NULL;
    }

    head->next = NULL; //带头结点的链表,只维护指针域,无需维护数据域

    return head;
}

功能:

创建一个链表的头结点,并返回给使用者

链表长度获取

链表统计 核心代码:
//统计链表长度
int size_list(LinkList head)
{
    if (head == NULL)
    {
        printf("传入链表为空\n");
        return 0;
    }
    Node * pCur = head->next;  //获取第一个有数据的结点

    int num = 0;
    while (pCur != NULL)
    {
        num++;
        pCur = pCur->next;
    }
    return num;
}

功能:

统计链表中结点的个数并返回

链表的插入

链表插入 核心代码:
//插入结点  参数1 链表的头结点   参数2  插入位置   参数3 插入数据
void insert_list(LinkList head, int pos , int val)
{
    if (head == NULL)
    {
        printf("传入链表为空\n");
        return;
    }

    if (pos < 0 || pos > size_list(head))
    {
        printf("插入位置无效\n");
        return;
    }

    //辅助指针,帮助我们找到待插入位置的前驱结点
    Node* pCur = head;
    for (int i = 0; i < pos; i++)
    {
        pCur = pCur->next;
    }

    //创建新结点
    Node* newNode = (Node *)malloc(sizeof( Node));
    if (!newNode)
    {
        return;
    }
    newNode->data = val;
    newNode->next = NULL;

    //将新结点插入到链表长
    newNode->next = pCur->next;
    pCur->next = newNode;
}

功能:

向指定的位置上,插入新的结点

链表的遍历

链表遍历 核心代码:
//遍历链表
void foreach_list(LinkList head)
{
    if (head == NULL)
    {
        printf("传入链表为空\n");
        return;
    }

    Node* pCur = head->next;  //拿到第一个有数据的结点

    while (pCur != NULL)
    {
        printf("%d ", pCur->data);
        pCur = pCur->next;
    }
    printf("\n");
}

功能:

打印链表中每个结点的数据域

链表的删除

链表删除 核心代码:
//删除结点  参数1  链表表头   参数2  删除位置
void delete_list(LinkList head, int pos)
{
    if (head == NULL)
    {
        printf("传入链表为空\n");
        return;
    }

    if (pos < 0 || pos > size_list(head) - 1)
    {
        
        printf("删除位置无效\n");
        return;
    }

    //辅助指针,帮助我们找到待删除位置的前驱结点
    Node* pCur = head;
    for (int i = 0; i < pos; i++)
    {
        pCur = pCur->next;
    }
    //记录待删除结点
    Node* pDel = pCur->next;
    //更改指针,删除结点
    pCur->next = pDel->next;
    //释放待删除的结点
    free(pDel);
}

功能:

删除指定位置上的结点

链表的清空

链表清空 核心代码:
//清空链表
void clear_list(LinkList head)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	//指向第一个有数据的结点
	Node * pCur = head->next;

	while (pCur != NULL)
	{
		//先保存住下一个节点的位置
		Node * pNext = pCur->next;

		//释放节点
		free(pCur);
		pCur = pNext;
	}

	head->next = NULL;

}

功能:

删除指定位置上的结点

链表的销毁

链表清空 核心代码:
//销毁链表
void destroy_list(LinkList head)
{
    if (head == NULL)
    {
        printf("传入链表为空\n");
        return;
    }

    //先清空链表
    clear_list(head);

    //将头结点也释放掉,完成整个链表的销毁
    free(head);
    head = NULL;
}

功能:

删除指定位置上的结点

完整代码:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct node
{
	int data;//数据域
	struct node* next; //指针域
}Node, *LinkList;  //Node是struct node的别名, LinkList 代表struct node*数据类型

//链表的初始化
LinkList creat_list()
{
	LinkList head  = (Node *)malloc(sizeof(Node));
	if (!head)
	{
		printf("内存分配失败\n");
		return NULL;
	}

	head->next = NULL; //带头结点的链表,只维护指针域,无需维护数据域

	return head;
}

//统计链表长度
int size_list(LinkList head)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return 0;
	}
	Node * pCur = head->next;  //获取第一个有数据的结点

	int num = 0;
	while (pCur != NULL)
	{
		num++;
		pCur = pCur->next;
	}
	return num;
}

//插入结点  参数1 链表的头结点   参数2  插入位置   参数3 插入数据
void insert_list(LinkList head, int pos , int val)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	if (pos < 0 || pos > size_list(head))
	{
		printf("插入位置无效\n");
		return;
	}

	//辅助指针,帮助我们找到待插入位置的前驱结点
	Node* pCur = head;
	for (int i = 0; i < pos; i++)
	{
		pCur = pCur->next;
	}

	//创建新结点
	Node* newNode = (Node *)malloc(sizeof( Node));
	if (!newNode)
	{
		return;
	}
	newNode->data = val;
	newNode->next = NULL;

	//将新结点插入到链表长
	newNode->next = pCur->next;
	pCur->next = newNode;
}


//遍历链表
void foreach_list(LinkList head)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	Node* pCur = head->next;  //拿到第一个有数据的结点

	while (pCur != NULL)
	{
		printf("%d ", pCur->data);
		pCur = pCur->next;
	}
	printf("\n");
}


//删除结点  参数1  链表表头   参数2  删除位置
void delete_list(LinkList head, int pos)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	if (pos < 0 || pos > size_list(head) - 1)
	{
		
		printf("删除位置无效\n");
		return;
	}

	//辅助指针,帮助我们找到待删除位置的前驱结点
	Node* pCur = head;
	for (int i = 0; i < pos; i++)
	{
		pCur = pCur->next;
	}
	//记录待删除结点
	Node* pDel = pCur->next;
	//更改指针,删除结点
	pCur->next = pDel->next;
	//释放待删除的结点
	free(pDel);
}

//清空链表
void clear_list(LinkList head)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	//指向第一个有数据的结点
	Node * pCur = head->next;

	while (pCur != NULL)
	{
		//先保存住下一个节点的位置
		Node * pNext = pCur->next;

		//释放节点
		free(pCur);
		pCur = pNext;
	}

	head->next = NULL;

}


//销毁链表
void destroy_list(LinkList head)
{
	if (head == NULL)
	{
		printf("传入链表为空\n");
		return;
	}

	//先清空链表
	clear_list(head);

	//将头结点也释放掉,完成整个链表的销毁
	free(head);
	head = NULL;
}
int main() {

	LinkList head = creat_list();  //创建链表,获取表头

	//打印链表长度
	printf("链表长度为:%d\n", size_list(head));

	//插入结点
	insert_list(head, 0, 10);
	insert_list(head, 0, 20);
	insert_list(head, 1, 30);
	insert_list(head, 0, 40);

	//遍历链表
	printf("插入结点后,遍历结果为:\n");  // 40 20 30 10 
	foreach_list(head);

	//打印链表长度
	printf("链表长度为:%d\n", size_list(head));

	//删除结点
	delete_list(head, 2);
	printf("删除结点后,遍历结果为:\n");  // 40 20 10
	foreach_list(head);

	//清空链表
	clear_list(head);
	printf("清空链表后,遍历结果为:\n");  
	foreach_list(head);

	//销毁链表
	destroy_list(head);

	system("pause");
	return EXIT_SUCCESS;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值