这是一个链表
每个结点由数据域和指针域组成,数据域存放数据,指针域存放下一个结点的地址,如果是最后一个结点,那么其指针域为空(nullptr);
首先我们要定义这样一个结点的结构:
struct ListNode
{
int val = 0;//存放数据//这里初始化为0
ListNode* next = nullptr;//存放下一个结点的地址//初始化为空
};
next 的类型为 ListNode* ,因为next指向了下一个结点,而下一个结点的类型为ListNode,指向ListNode类型的指针是ListNode* 型。
我们来创建一个结点:
ListNode newnode;//如果是C语言则不可以省略struct
向这个结点里添加数据:
newnode.val = 6;
让这个结点指向下一个结点:
ListNode nextnode;//新建下一个结点
newnode.next = &nextnode;//存放下一个结点的地址
在c++里我们可以用构造函数来初始化:
关于c++构造函数可参考:C++构造函数的三种写法 - 知乎 (zhihu.com)
struct ListNode {
int val;
ListNode* next;
//函数重载
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
这样我们便可以用类似 ListNode newlistnode (2); 这样的语句进行初始化了;
为了方便的找到这个链表,我们可以用一个指针来指向这个链表的第一个结点:
ListNode* head = &newnode;
为了方便链表的插入和删除,我们可以使用c++的new运算符来创建一个链表:
int main()
{
ListNode* head = nullptr;//创建头指针,初始为空
ListNode* cur = head;//创建临时指针,以便向后添加结点,因为头指针在这里是不能动的,要一直指向第一个结点
int N;//你要创建的链表的长度
cin >> N;
while (N--)
{
if (head == 0)//如果头指针为空,则指向第一个结点
{
int val;//该节点要存贮的数据
cin >> val;
cur = new ListNode(val);//用new函数创建一个结点,并用临时指针指向它
head = cur;//头指针指向第一个结点
}
else
{
int val;
cin >> val;
ListNode* p = new ListNode(val);//用new函数创建一个结点,并新建一个p指针指向它
cur->next = p;//将新结点的地址赋给前面结点的next指针域
cur = cur->next;//临时指针后移
}
}
return 0;
}
还有一个带有虚拟头结点的链表,头结点是为了方便链表的插入和删除等操作(具体操作将在下节讲解)如果要为一个已经有头指针的链表添加一个头结点(图第三种情况),则可以按如下方式:
ListNode* dummyhead = new ListNode();
dummyhead->next = head;
虽然头结点的数据域一般无意义,但有时候也可以用来存放如链表的长度等数据。
如果是双链表,则在结点的结构里加上一个指针指向前一个结点
如果是循环链表,则让最后一个结点的next指向第一个结点
这里不多赘述