链表 [1] —— 静态链表节点的增删、遍历以及链表节点数的统计(笔者第一篇C语言博客)

文章转载请注明出处,加上原文地址链接,谢谢!https://blog.csdn.net/weixin_46959681/article/details/110536329



什么是数据结构

数据结构就是研究数据的逻辑结构和物理结构以及它们之间的相互关系,并对这种结构定义相应的运算,而且确保经过这些运算后得到的新的结构体仍然是原来的结构体。


什么是链表

数据结构决定了数据的顺序和位置关系。 链表属于数据结构的思想之一。链表操作之后结果仍然是链表。在链表中数据呈现线性排列,其中数据的添加和删除都较为方便。

顺序访问。 存储于链表中的数据一般都是分散存储于内存中,无需存储在连续空间内,因此数据的访问比较耗费时间。 因此若想找到数据 Red ,必须要从数据 Blue 开始。

顺序访问

添加数据。 在链表中添加数据,只需要改变添加位置前后的指针指向即可。

添加数据


常用的链表有哪些

循环链表:循环链表没有头和尾的概念,尾部用一个指针指向头部。使用该链表用于保存数量固定的最新数据。
循环链表

代码演示: color.c

/* color.c */
#include <stdio.h>

struct color
{
    
     		
	int data;
	//指针在没有被赋予指向的对象时为一个野指针NULL。
	struct color *next;
};

int main()
{
    
    	
	struct color Blue = {
    
    1,NULL};
	struct color Yellow = {
    
    2,NULL};
	struct color Red = {
    
    3, NULL};

	//三者通过指针操作建立了一个循环。
	Blue.next = &Yellow; 
	Yellow.next = &Red;
	Red.next = &Blue;

	//为了配上蓝、黄、红三个节点的指针指向,故使用了这种比较土的写法。
	printf("%d %d %d\n", Blue.data, Blue.next->data, Blue.next->next->data); 	
	return 0;
}

双向链表:链表里的每个数据都有两个指针,让其分别指向前后数据。这种链表不仅能从前往后,还可以从后往前遍历数据。但双向链表存在两个缺陷:一是指针数量的增加的会导致存储空间需求增加;二是添加和删除数据时需要改变更多指针的指向。
双向链表

四张图片来自《我的第一本算法书》。


静态链表的增删

在下面的代码中,笔者在使用结构体以及使用指针访问结构体的方式创建了一个只有四个节点的静态链表,从代码里可以看到该链表中仅有四个数据。相比于大小固定的数组,链表在增删数据方面十分简便,可以直接在代码中增加结构体成员和相应的指针操作完成增删,如新增节点 t5 。删除节点仅需删除对应节点的代码。


使用while循环实现链表的遍历和节点的统计

在代码中使用封装的函数 getLinkTotalNodeNum() 实现节点的统计和 printLink() 实现链表的遍历,请直接阅读代码。

#include <stdio.h>

struct Test
{
    
     	
	int data;
	//结构体中的指针指向是链表的核心操作。
	struct Test *next; 
};

int getLinkTotalNodeNum(struct Test *head)
{
    
     		
		//统计链表节点数。
        int count = 0;
        struct Test *point;
        //保留链表头。 
        point = head; 
        while(point != NULL)
        {
    
    
                count++;
                //指针位移。
                point = point->next;
        }
        return count;
}

void printLink(struct Test *head)
{
    
     
	//遍历链表。
	struct Test *point;
	point = head;
	printf("链表遍历:");
	while(point != NULL)
	{
    
    
		printf("%d ", point->data);
		//在循环中进行指针位移达到遍历链表的目的。
		point = point->next; 
	}
	putchar('\n');
}

int main()
{
    
    
	struct Test t1 = {
    
    1,NULL};
	struct Test t2 = {
    
    2,NULL};
	struct Test t3 = {
    
    3,NULL};
	struct Test t4 = {
    
    4,NULL};
	//新增的第五个节点。
	struct Test t5 = {
    
    5,NULL}; 
	
 
  	//第一个节点为链表头。
	struct Test *head; 
	head = &t1;
	
	t1.next = &t2;
    t2.next = &t3;
   	t3.next = &t4; 
   	//第四个节点的指针域内部的指针指向了新增的第五个节点。
   	t4.next = &t5; 
   	
   	//将链表头作为参数传递给函数 printLink()。
	printLink(head); 
	int ret = getLinkTotalNodeNum(head);
	printf("链表节点数:%d\n", ret); 
	return 0;
}

第一次写编程语言相关的博客

笔者作初学C语言编程的新手,学习过程中仅基于自己粗糙的理解和相应的资料做出本人的第一篇C语言博文。后天笔者会写出第二篇博客——指定节点的前方、后方插入新节点等内容。


文章更新记录

  • 文章大体初步完成。「2020.12.3 22:13」
  • 链表节点统计与遍历合并为一节。「2020.12.4 15:47」
  • 增加循环链表的代码演示。「2020.12.4 20:00」
  • 修改了演示用的代码。「2020.12.5 10:40」
  • 循环链表中的代码错误修该完毕。「2020.12.8 10:28」
  • 修改了演示用的代码。「2021.1.9 14:50」
  • 修改了演示用的代码。「2021.2.7 20:41」

猜你喜欢

转载自blog.csdn.net/weixin_46959681/article/details/110536329