链表的基础知识
空指针:nullptr,用于表示指针不指向任何有效的内存地址。
int *p=nullptr;
链表的定义
struct ListNode
{
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(nullptr) {} // 节点的构造函数
};
链表中有指针域和数据域,指针域指向下一个结点的地址,数据域保存链表数据,尾结点的下一个结点的地址为nullptr.
默认构造函数不定义也没有关系,但是定义之后会方便链表初始化
不定义默认构造函数时候初始化链表
ListNode *node=new ListNode();
node->val=5;
定义默认构造函数时候:
ListNode *node=new ListNode(5);
链表的操作
定义一个虚拟头节点dummyHead和当前节点cur
ListNode *dummyHead = new ListNode(0); // 定义了虚拟头结点
这个头结点数据域不存放数据,指针域(dummyHead->next为第一个节点的地址)
为什么要定义头结点:一般来说都要
同时,还需要一个指向当前节点的指针cur,刚开始指向dummyHead
ListNode *cur = dummyHead; // 指针cur指向虚拟头节点
链表节点初始化值
如果要在链表节点定义一个值
int val;
cin>>val;
ListNode *newNode = new ListNode(val);
遍历链表节点
cur=dummyHead;//当前节点从头开始遍历
while(cur->next!=nullptr)
{
cur=cur->next;
}
链表第n个节点位置的寻找
// 指针重新指向虚拟头结点,准备用cur遍历链表
cur = dummyHead;
// 寻找添加节点的位置,i从1开始,
for (int i = 1; i < n; i++) {
cur = cur->next;
}
构建一个链表(n个元素)
for (int i = 0; i < n; i++) { // 或者使用while(n--)
cin >> val; // 输入链表节点的val值
ListNode *newNode = new ListNode(val); // 根据val值构造一个新的节点
cur -> next = newNode; // 当前指针的下一个节点为新节点,从而将新节点接入链表
cur = cur -> next; // cur 指向下一个节点(也就是新创建的节点)
}
添加节点
假设目前的尾结点是cur,那么插入操作就是
1.创建一个新的结点,让cur->next变为当前节点的地址
2.把当前节点变为尾结点
ListNode *newNode = new ListNode(val); // 通过new构造一个新的节点,节点的值为val
cur -> next = newNode; // cur节点的next节点是新节点,从而将新节点接入链表
cur = cur -> next; // 新插入的节点变更为新的尾节点,即cur发生了变更
删除
// 删除节点
cur->next = cur->next->next;
打印链表
// 打印链表
void printLinklist(ListNode* dummyHead) {
ListNode* cur = dummyHead;
while (cur->next != NULL) {
cout << cur->next->val << " ";
cur = cur -> next;
}
cout << endl;
}