我正在阅读其中一本书并坚持一个特定的问题。
链表的结构定义:::
typedef struct LinkedList{
LinkedList* next;
int data;
}
书中说“将下一个指针放在结构或类的开头可以很容易地编写通用的列表处理例程,无论数据是什么。”
我无法理解如何将下一个指针置于顶部将有助于此。
另外,要制作通用列表,我们不需要将数据类型作为泛型或者说是void *?
答案 0 :(得分:2)
你正在看的那本书编程访谈暴露,是(据我所知)不是一本关于C ++的书,而是一本书准备好回答在典型的技术面试中可能会提出的问题。我不会把这本书中的任何东西都当作最好的C ++实践,除非它被标记为(甚至可能不是那样)。
将下一个指针置于链表节点结构中的建议来自C语言,您不能依赖实际的,编译器支持的继承。事实上,这个想法是通过将数据搭载到链表节点结构上来自己实现继承。考虑:
typedef struct LinkedList {
LinkedListNode* next;
int type;
}
typedef struct Person {
LinkedList listNode;
char name[64];
int age;
}
typedef struct Address {
LinkedList listNode;
char streetAddress[128];
char city[32];
char state[2];
char zip[10];
}
typedef struct Employee {
Person person;
int department;
int salary;
}
这里的LinkedList是一种基本类型 - 本身并不好用,但作为具有更多数据的节点的起点非常有用。您无需了解其他类型以便在节点上执行链接列表操作...您可以将任何节点指针强制转换为LinkedList *并访问您需要的信息。因此,您可以拥有Person列表和Address列表,并且可以使用同一组例程操作它们。同样,您可以将Employee *转换为Person *,并使用您为Employee上的Person编写的任何操作。如果为LinkedList的type
字段分配适当的常量,您甚至可以混合使用PersonNode并使用type
字段来确定每个节点的类型。
这是20多年前编程的有用方法。当然,它仍然可以工作,但是如果有选项的话,大多数人都会选择让编译器为它们管理继承,并且所有现代的面向对象语言都提供该选项。
课程:如果您在旧代码中遇到此技术,请了解该技术,但如果可以,请为新代码选择不同的实现。
答案 1 :(得分:1)
如果将下一个指针放在开头,并且你拥有的只是一个void *,但是你知道它是一个链表节点,你总能找到下一个指针。这与放置在“数据”之后的下一个指针形成对比,假设“数据”可以具有不同的大小,您需要了解有关该对象的更多信息才能找到下一个指针
答案 2 :(得分:0)
我个人认为没有任何理由,我同意,这个论点应该是模板化的:
template <class T> class ListElement
{
T data;
ListElement* next;
...
}
关于速度可能存在一些问题,内存对齐方式反过来要好一些,但我对此表示怀疑!
HTH
马里奥