巩固单链表知识。
透过结构体定义一个单链表。
struct ListNode {
int value;
ListNode* next;
};
头插法:
头插法即从头部插入,实际上就是反着插,先插入的在后面,每一个新插入的都是头节点
void addhead(ListNode *& head ,int value) {
ListNode* newnode = new ListNode;
newnode->value = value;
newnode->next = head ;
head = newnode;
}
int main() {
ListNode* head = nullptr;
addhead(head, 2);
addhead(head, 3);
addhead(head, 4);
}
这里的参数,必须使用引用。任何情况下,使用“指针传递”,传入的都是指针的副本,如果函数中修改了指针指向的值,似乎和引用传递效果一样,但如果函数中对指针进行了处理,则需要传入【指针的引用】才行,否则的话对指针做的操作不会影响到原来的指针。
在这个函数中,我先创建了一个newnode,它的value是传入的value,它的指针指向的看似是一个ListNode,但实际上是个nullptr。
这个newnode是第一个节点,同时也是尾节点。【谁是尾节点?】是newnode,不是head,此时head还是个nullptr。只是在最后一行,我把newnode指向的内容交给了head维护。
把newnode给到head,那么下次传入时,head便是这个尾节点,它的值是value,它的指针指向nullptr。
第二次,我又创建了一个newnode,把它的next指向listnode,同时给value赋值。这样,就把这个节点插入到了上个节点head的上一个位置【last】。然后把newnode给到head,取代原来的head成为头节点。
下面写尾插法:
也就是顺序插法
void addtail(ListNode*& head, int value) {
ListNode* newnode = new ListNode;
newnode->value = value;
newnode->next = nullptr;
if (head == nullptr) {
head = newnode;
}
else {
//遍历得到尾节点
ListNode* currentnode = head;
while (currentnode->next != nullptr) {
currentnode = currentnode->next;
}
currentnode->next = newnode;
}
}
int main() {
ListNode* head1 = nullptr;
addtail(head1, 2);
addtail(head1, 3);
addtail(head1, 4);
addtail(head1, 5);
}
在这个函数中,我创建了一个newnode,作为第一个节点,
当head是nullptr时,说明当前创建的是头节点,把newnode给到head,来维护head。
此时head便不再是 nullptr,传入的参数走第二路径,
把head给到currentnode,并且循环遍历,不断地将next值给到currentnode,直到没有next值。
将currentnode的next设为刚刚创建的newnode。
由于创建的链表都是new开辟的空间,需要写一个方法,通过head释放内存
void clearlist(ListNode*& head) {
ListNode* currentnode = head;
while (currentnode->next != nullptr) {
ListNode* temp = currentnode;
currentnode = currentnode->next;
delete temp;
}
head = nullptr;
}