数组和矢量都属于顺序存储结构(顺序表),由于链表和顺序表在存储结构上的差异,导致它们具有不同的特点,适用的应用场景也有所差异,感兴趣的小伙伴请猛击这里了解详情。
因为指向链表头的指针用于定位链表的头部,所以也可以认为它代表了链表头。同样的指针也可以用来定位整个链表,从头开始,后面跟着后续指针,所以也可以很自然地把它看作是代表了整个链表。nullptr 是 C++11 新增的一个关键字,专门替代 NULL、0 来初始化指针。和 NULL、0 相比,nullptr 可以使程序更健壮,具体原因请猛击这里了解详情。
struct ListNode { double value; ListNode *next; };
在以上代码中,ListNode 就是要存储在链表中的结点的类型,结构成员 value 是结点的数据部分,而另一个结构成员 next 则被声明为 ListNode 的指针,它是指向下一个结点的后继指针。注意,C++ 中的 struct 不仅可以定义结构体,还可以定义类(只是通常不这么做)。在 C++ 中,struct 和 class 基本是通用的,只有几个细节不同,感兴趣的小伙伴请猛击这里了解详情。
ListNode *head = nullptr;
现在可以创建一个链表,其中包含一个结点,存储值为 12.5,如下所示:head = new ListNode; //分配新结点 head->value = 12.5; //存储值 head->next = nullptr; //表示链表的结尾接下来再看一看如何创建一个新结点,在其中存储 13.5 的值,并将其作为链表中的第二个结点。可以使用第二个指针来指向新分配的结点(其中将存储 13.5 的值),示例如下:
ListNode *secondPtr = new ListNode; secondPtr->value = 13.5; secondPtr->next = nullptr; //第二个结点是链表的结尾 head->next = secondPtr; //第一个结点指向第二个请注意,以上语句通过将其后继指针 secondPtr->next 设置为 nullptr,可以使第二个结点成为链表的结尾,通过 head->next = secondPtr; 语句将链表头的后继指针改为指向第二个结点。
// This program illustrates the creation || of linked lists. #include <iostream> using namespace std; struct ListNode { double value; ListNode *next; }; int main() { ListNode *head = nullptr; // Create first node with 12.5 head = new ListNode; // Allocate new node head->value = 12.5; // Store the value head->next = nullptr; // Signify end of list // Create second node with 13.5 ListNode *secondPtr = new ListNode; secondPtr->value = 13.5; secondPtr->next = nullptr; // Second node is end of list head->next = secondPtr; // First node points to second // Print the list cout << "First item is " << head->value << endl; cout << "Second item is " << head->next->value << endl; return 0; }程序输出结果:
First item is 12.5
Second item is 13.5
struct ListNode { double value; ListNode *next; //构造函数 ListNode(double valuel, ListNode *nextl = nullptr) { value = value1; next = next1; } };通过该声明,即可使用以下两种不同的方式创建一个结点:
ListNode *secondPtr = new ListNode(13.5);
ListNode *head = new ListNode(12.5, secondPtr);
ListNode *head = new ListNode(13.5);
head = new ListNode(12.5, head);
head = new ListNode(12.5, head);
该语句将从右到左评估,首先在构造函数中使用 head 的旧值,然后从 new 运算符返回的地址将被分配给 head,成为它的新值。ListNode *numberList = nullptr; double number; while (numberFile >> number) { //创建一个结点以保存该数字 numberList = new ListNode(number, numberList); }
ListNode *ptr = numberList;
然后就可以通过使用表达式 *ptr 或者使用结构指针操作符 -> 来处理由 ptr 指向的结点。例如,如果需要打印在结点上的值,则可以编写以下代码:cout << ptr->value;
一旦在该结点的处理完成,即可将指针移动到下一个结点(如果有的话),其语句如下:ptr = ptr->next;
以上语句使用指向结点后继的指针来替换了指向该结点的指针,实现了结点之间的移动。因此,要打印整个链表,可以使用如下代码:ListNode *ptr = numberList; while (ptr != nullptr) { cout << ptr->value << " "; //处理结点(显示结点内容) ptr = ptr->next; //移动到下一个结点 }下面的程序演示了上面所介绍的各种技巧,即读取文件中的数字,将数字排列在链表中,然后通过遍历链表将数字显示在屏幕上。
// This program illustrates the building // and traversal of a linked list. #include <iostream> #include <fstream> using namespace std; struct ListNode { double value; ListNode *next; // Constructor ListNode(double value1, ListNode *next1 = nullptr) { value = value1; next = next1; } }; int main() { double number; // Used to read the file ListNode *numberList = nullptr; // List of numbers // Open the file ifstream numberFile("numberFile•dat"); if (!numberFile) { cout << "Error in opening the file of numbers."; exit (1); } //Read the file into a linked list cout << "The contents of the file are: " << endl; while (numberFile >> number) { cout << number << " "; // Create a node to hold this number numberList = new ListNode(number, numberList); } // Traverse the list while printing cout << endl << "The contents of the list are: " << endl; ListNode *ptr = numberList; while (ptr != nullptr) { cout << ptr->value << " "; // Process node ptr = ptr->next; // Move to next node } return 0; }程序输出结果:
The contents of the file are:
10 20 30 40
The contents of the list are:
40 30 20 10
Copyright © 广州京杭网络科技有限公司 2005-2025 版权所有 粤ICP备16019765号
广州京杭网络科技有限公司 版权所有