在写一个索引文件前,我们通常需要了解树这个概念,因为在内存中存放的数据结构的实现,大多数是由树构成的,而树在内存中的实现是通过指针的方式实现。学习树的实现方式通常是在内存中的建立和遍历,而没有拓展到文件中,这就导致了很多人只了解到一些书面的练习,而没有在实际中进一步运用,比如将内存中的组织形式存入到文件中,因为除非内存数据库那种形式,否则大批量的数据仍然需要落地到文件,并且建立索引文件以便进一步组织各数据文件的逻辑关系。
内存中树的实现较为简单的是二叉树,在实现二叉树的文件存储前,我们试着实现链表的文件存取。
链表通常是在内存中实现的,包括链表的定义、链表的数据节点的建立、链表的数据访问读取、链表的节点插入和删除。我们重新复习相关的知识点,试着定义链表、建立链表、做数据输入,先做内存部分实现。
point.cpp
#include <iostream>
/*
--链表建立,写入文件,从文件中读取链表。
Finished 20240115
by Racyen
*/
//定义链表的基础节点
typedef struct Node{
int data;
struct Node * next;
}Node;
链表由一个数据data和一个指针 next构成,next指向链表的下一个节点。
下面开始通过节点建立链表
//建立链表
Node *createLinkTable(){
int n=5;//我们假设建立链表的节点数是5,或者这个可以当做函数的参数进行入参设置,为了理解,我们仅做固定数值定义为5。
//链表头指针,初始化的时候指向一个空节点
Node *head ;//理解为指针指向某一节点区域,指针并不具有结构体的数据结构,因为该结构体是16个字节,而指针是8个字节,指针只存放结构体的地址。
//这时的头结点是空的;
//=(Node *)malloc(sizeof(Node));
//下面的printf部分是用于调测。
printf("*head is %d\n",*head);
printf("head size is %d\n",sizeof(head));
printf("head is %d\n",head);
printf("head add is %d\n",&head);
//定义游标指针,这个相当于建立链表的过程中追踪当前链表末节点
Node *current=head;
printf("*current is %d\n",*current);
printf("current size is %d\n",sizeof(current));
printf("current is %d\n",current);
printf("current add is %d\n",¤t);
//增加n个结点,这是建立链表数据的部分
for(int i=0;i<n;i++)
{
Node *newNode=(Node *)malloc(sizeof(Node));
printf("Enter value of node %d :",i+1);
scanf("%d",&newNode->data);
current->next=newNode;//将追踪节点与新节点相连
current=newNode;//将追踪节点存放的地址换成或者叫更新成新节点的地址,这个地方好好理解。这样追踪节点从前一节点就后移了一个节点。
}
current->next=NULL;
return head;
}
我们建立链表后可以打印一下链表,验证数据的正确性
//打印链表
void printLinkTable(const Node *head)
{
Node *current =head->next;//因为链表头是空内容,从头结点的下一个节点开始;
int i=0;
//这个地方我为了研究内存中数据的展示,将各种格式都打印出来,用于进一步理解并学习。
printf("头结点\n");
printf("-------------------------------------------------------\n" );
printf("Node size is %d\n",sizeof(Node));
printf("-------------------------------------------------------\n" );
printf("*head size is %d\n",sizeof(*head));
printf("*head is %d\n",*head);
printf("-------------------------------------------------------\n" );
printf("head size is %d\n",sizeof(head));
printf("head is %d\n",head);
printf("head is %d\n",&head);
printf("-------------------------------------------------------\n" );
printf("head->data size is %d\n",sizeof(head->data));
printf("head->data is %d\n",head->data);
printf("-------------------------------------------------------\n" );
printf("head->next size is %d\n",sizeof(head->next));
printf("head->next is %d\n",head->next);
printf("-------------------------------------------------------\n" );
while(current!=NULL)
{
i++;
printf("第%d个结点\n",i);
printf("-------------------------------------------------------\n" );
printf("Node size is %d\n",sizeof(Node));
printf("-------------------------------------------------------\n" );
printf("*current size is %d\n",sizeof(*current));
printf("*current is %d\n",*current);
printf("-------------------------------------------------------\n" );
printf("current size is %d\n",sizeof(current));
printf("current is %d\n",current);
printf("-------------------------------------------------------\n" );
printf("current->data size is %d\n",sizeof(current->data));
printf("current->data is %d\n",current->data);
printf("-------------------------------------------------------\n" );
printf("current->next size is %d\n",sizeof(current->next));
printf("current->next is %d\n",current->next);
printf("-------------------------------------------------------\n" );
current=current->next;
}
}
通过以上步骤,链表就建立好了。
通常书本上的内容讲到此就结束了,这也是许多年前我们在学习时到达的那个阶段,但是为了进一步理解文件系统的作用以及为了进一步提升自己的水平,我们需要更上一层楼。
下一节我们试着实现将链表数据写入文件,从而达到文件作为存储的作用。因为很多年前,我的老师在讲课时反复强调,如果没有对文件有所理解,那对程序的理解是十分肤浅的,也就是做不出什么太深入的程序。而观如今,发展的区块链、分布式文件系统、分布式存储无一不表明了这个观点,还有日趋形成的国产化去IOE的事情,国产数据库的研发,也将文件的存储使用作为一个必须攻克的事宜。因为离校多年,至今不知学弟学妹们在学校是学到了哪些知识,是停留在内存层面,还是到文件存储层面?运用的如何,对这些基础的知识是否已经深入理解,至少我在学校的当年是周边很少有人对文件做进一步的研究的,也可能大家为了学分达标而已,没有做太深入的研究。也是基于一些自身的想法和多年以来一直想做的一些事情,故以不忘初心的念想,来拾起或者重温当年未完成的一些事宜,凭着自己的不断感悟,还通过拙码来验证自己的一些思路和想法吧。