C中链表的总大小

好吧……我对CS数据结构的介绍是如此生疏,我需要在这里提出这个问题。

我有一个链表,其结构是:

struct Data_Struct { char *Name; char *Task; char *Pos; struct Data_Struct *Next; }; typedef struct Data_Struct MyData; 

现在,在我的应用程序的某个时刻,我用数据填充了列表。

问题是,如何获得存储在那里的数据的总大小? 有多少个字符? 就像是

 sizeof(MyData); 

这将返回列表中存储的信息的大小。

代码表示赞赏。

谢谢!

编辑 :不幸的是这不是功课。 我在20多年前完成了学业,坦率地说,我从来没有在任何事情上使用链接列表。 我只是不记得了。 我正在做的是迭代列表并获取每个元素的strlen()并将其保持在全局大小但我想知道是否有更好的方法。

和NO,我不需要链接的喜欢的大小(节点的数量),我只想知道那里存储了多少个字符。

谢谢

您通常会遍历列表,直到您到达尾部项目,同时计数,代码应该是这样的:

 int listLength(struct Data_Struct* item) { struct Data_Struct* cur = item; int size = 0; while (cur != null) { ++size; cur = cur->Next; } return size; } 

请注意,此操作的复杂性与列表的大小成线性关系,因此它是O(n)并且效率非常低。 您可以在某处存储大小并使用列表插入和删除进行更新,以避免任何开销并能够在恒定时间O(1)内计算它。

编辑:没有注意到你想要包含在列表中的整个数据的大小。 在您的情况下,您可以保持用于计算长度的相同方法,但是为每个元素添加1 ,您应该添加字符串的总长度:

 size += strlen(Name)+strlen(Task)+strlen(Pos); 

请注意,由于list元素中的数据(如果是char*类型) char*的有效大小只有4个指针,这就是为什么你需要使用像strlen这样的支持函数,否则你无法获得字符串的真实维度。

有什么区别?

 sizeof(Data_Struct) == 16 

因为Data_Struct类型包含4个指针,3个用于指向char的指针,1个指针用于列表中的下一个元素

 sizeof(Name) == sizeof(Task) == sizeof(Pos) == 4 

因为这些变量是char的类型指针 ,所以它们是指针,没有具体的值,它通常是4个字节(我假设是32位架构)

 strlen(Name) == length in chars of the string 

因为该函数完全可以计算字符串的长度。

那么,你可以遍历列表来很容易地计算计数。 显然,总内存将等于项目数乘以每个项目的大小( sizeof(Data_Struct) )。

当然,这将是链表本身的大小,不包括为字符串分配的内存。 指针没有关于它所引用的已分配内存量的任何信息,因此严格来说,只能通过查看链接列表来计算直接分配的总内存量。 此外,您需要跟踪链接列表中可能存在重复的指针。 也就是说,假设所有指针都是唯一的,您可以通过在遍历列表时对每个指针上的strlen调用的返回值求和来计算每个项中的字符数(这应该非常简单)。

为节点分配内存后(使用malloc),您应该能够执行sizeof(yourDataType)。 因此,要获取链表的总大小,请遍历列表并获取节点数:

 Total Size Of Linked List = SizeOf(One Node) * Count Of Nodes 

例如:

 int getCountOfList() { Node* temp = head; //assign a temp node to the head of the list int count=0; while(temp) { count++; temp = temp->next; //move to next node } return count; } 

然后你取这个数并乘以大小:

size = getCountOfList * sizeof(mydatatype);

这将为您提供实际链表的大小,但因为链表节点具有指针元素,这些指针元素本身也可以分配内存。 这将需要考虑…

例如,节点中的其中一个char *元素可能会占用更多空间并占用一些内存。

如果您确实需要列表的整个大小,包括所有其他char *指针的已分配元素,例如,您只需:

1)遍历列表并查看每个节点

2)对于每个节点,检查每个节点的元素是否指向任何其他分配(例如char * data可以分配50个字符来存储)。 如果它不为null,则获得字符串长度+ 1(用于终止char),然后将其乘以sizeof(char)(对于此示例)

3)您为每个节点执行此操作并存储该大小,然后移至下一个节点

4)为每个节点获取所有这些char *(在本例中)的SUM,并为整个列表累积。

5)一旦你有了,只需添加这个总和,它将给你所有节点的大小。

然后总大小变为:

 SizeOfAllNode + (SizeOf(dataType) * CountOfNodes) 

添加或删除节点时保持运行计数。 这样,您就不必走列表,每次想要计数时总结每个节点。 只需参考您的最新价值。

要计算列表本身的大小,只需取sizeof(MyData)并乘以节点数。

如果要在列表中包含字符串数据的大小,可以将字符串使用的内存计算为(strlen(str) + 1) * sizeof(char) – 当然假设字符串已分配给完全合适的尺寸。

如果您需要多次获取数据的大小,那么在向列表中添加元素时跟踪它会更明智,但是用来计算出暴力的代码非常简单。

  size_t cb = 0; int cItems = 0; struct Data_Struct * pnext = &MyData; while (pnext) { if (pnext->Name) cb += (strlen(pnext->Name)+1) * sizeof(char); if (pnext->Task) cb += (strlen(pnext->Task)+1) * sizeof(char); if (pnext->Pos) cb += (strlen(pnext->Pos)+1) * sizeof(char); ++cItems; pnext = pnext->Next; } // cb has the total size of the strings, now add the size of the data structs cb += sizeof(struct Data_Struct) * cItems; 

您可以遍历列表中的所有成员并累计Name,Task和Pos上的字符数。

但是,如果您打算多次这样做,我会在填充节点时存储每个字段的字符数,而不是一次又一次地计算它们。

因此,您的结构将定义如下:

 struct Data_Struct { char *Name; int NameCount; char *Task; int TaskCount; char *Pos; int PosCount; struct Data_Struct *Next; }; typedef struct Data_Struct MyData; 

并遍历列表可能是这样的:

 void getCharacterCount(struct Data_Struct* data, int* nameCount, int* taskCount, int* posCount) { struct Data_Struct* auxData = data; int nc = tc = pc = 0; for (; auxData; auxData = auxData->Next()) { nc += auxData->NameCount; tc += auxData->TaskCount; pc += auxData->PosCount; } *nameCount = nc; *taskCount = tc; *posCount = pc; }