我的方法是,先了解链表的原理,然后书写代码
1.了解new的用法,如何开辟内存
2.如何写函数封装
3.如何遍历链表
4.如何实现函数功能
5.如何写代码,并真正了解链表如何使用
6.能独立写一个链表函数
7.能够独立写出来一个双链表
首先就是leetcode上的水题203. 移除链表元素 - 力扣(LeetCode)
有两种写法,一种是非虚拟节点法
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//删除头结点
while(head!=NULL&&head->val==val){
ListNode *temp=head;
head=temp->next;
delete temp;
}
//如果不是头结
ListNode* cur=head;
while(head!=NULL&&cur->next!=NULL){
if(cur->next->val==val){
ListNode* temp=cur->next;
cur->next=cur->next->next;
delete (temp);
}
else {
cur=cur->next;
}
}
return head;
}
};
这种写法唯一注意的地方就是是
cur->next=cur->next->next;
因为这是你的cur的指针指向的东西,是他的下一个要指向下下个节点,懂否?
cur只是一个当前的地址而已
第二种是虚拟节点的方法
可以和插入法结合起来使用,也就是形式一致
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//设置一个新的虚拟头结点
ListNode *dummyhead =new ListNode(0);
dummyhead->next=head;
ListNode* cur=dummyhead;
while(head!=NULL&&cur->next!=NULL){
if(cur->next->val==val){
ListNode* temp=cur->next;
cur->next=cur->next->next;
delete (temp);
}
else {
cur=cur->next;
}
}
head=dummyhead->next;
delete dummyhead;
return head;
}
};
这一点的head!=NULL可以不要因为cur指向的第一个就是head;
记住最后一步要把链表给收回来,把头结点重新安装回去,不要忘记了链表的结构啊,会报错的
class MyLinkedList {
public:
struct LinkNode {
int val;
LinkNode* next;
//cpp的创建链表的一种方式
LinkNode(int val):val(val), next(nullptr){}
};
//要先进行定义
private:
int size;
LinkNode* dummynode;
MyLinkedList() {
dummynode = new LinkNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
size = 0;
}
int get(int index) {
if(index<0||index>size-1){
return -1;
}
//这个不需要赋予它个结构体的嘞,因为真的很不需要LinkNode * cur=new LinkNode(0);
LinkNode* cur=dummynode->next;
while(index--){
cur=cur->next;
}
return cur->val;
}
void addAtHead(int val) {
LinkNode *newHead=new LinkNode(val);
//这里最好先把指针指向head以便于后面的操作,在中间插入节点,形成统一
newHead->next = dummynode->next;
dummynode->next=newHead;
size++;
}
void addAtTail(int val) {
LinkNode* LastNode=new LinkNode(val);
LinkNode* cur=dummynode;
//int size_num=size;
while(cur->next!=nullptr){
cur=cur->next;
}
cur->next=LastNode;
LastNode->next=NULL;
size++;
}
void addAtIndex(int index, int val) {
if(index>size)return;
if(index<0)index=0;
LinkNode *newNode=new LinkNode(val);
LinkNode* cur=dummynode;
while(index--){
cur=cur->next;
}
newNode->next=cur->next;
cur->next=newNode;
size++;
}
void deleteAtIndex(int index) {
if(index<0||index>size-1){
return;
}
LinkNode *cur=dummynode;
while(index--){
cur=cur->next;
}
LinkNode *temp=cur->next;
cur->next=cur->next->next;
delete temp;
temp=nullptr;
size--;
}
void printLinkList(){
if(size=0)return ;
LinkNode *cur=dummynode;
while(cur->next!=NULL){
cout<<cur->next->val;
cur= cur->next;
}
cout<<endl;
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
本题就是手搓一个链表的一些功能,实现一个动态链表,还是非常好的一个题,让我这个链表渣滓都略知1,2单向链表的用法了,建议熟练掌握,还有本题的一些关键点
1.一定要事先声明好,结构体指针,免得报错
2.一定要注意cur指向的对象,cur->next
3.一定要在脑子里建立一张链表,知道在链表增删改查的过程,脑子要很清醒,要拿笔去算,OK?脑子要灵活一点儿