链表学习|L203.移除链表元素、L707.设计链表、L206.反转链表

链表相关知识:

单链表:通过指针串联在一起的线性结构,由两部分组成,一部分数据域,一部分指针域,通过结构体来对其进行创建,其包含一个数值,一个指针(指向下一个链表),还有一个构造函数

双链表:包含两个指针,一个指向前面一个指向后面

存储结构:链表的内存是不连续的,而是散乱分布,每次定义链表的时候都需要new一块内存

链表定义:

Struct ListNode
{

    int val;

    ListNode *next;

    ListNode(int x):val(x),next(NULL){}

}

链表的基础操作:删除,增加

为了方便链表的操作,通常设置头结点,头结点的数值域为空(也可以存储线性表长度等附加信息)

但指针指向头链表的第一个节点

L203.移除链表元素https://leetcode.cn/problems/remove-linked-list-elements/

#include<iostream>
using namespace std;

//定义链表
struct ListNode {
	int val;
	ListNode* next;
	//构造函数
	ListNode():val(0),next(NULL){}
	ListNode(int val) :val(val), next(NULL) {}
	ListNode(int val,ListNode*next):val(val),next(next){}
};
//解法一:
//本题考查对链表删除操作,即从头结点开始遍历,找到当前链表的值
//将上一指针指向下一链表
class Solution {
public:
	ListNode* removeElements(ListNode* head, int val) {
		//判断当前头结点的val是否等于val
		//循环条件就是head!=NULL,和head->val==val,若等于,就先用一个指针指向当前head,然后再把当前head指向head指向的下一个链表
		while (head != NULL && head->val == val)
		{
			ListNode* solve = head;
			head = head->next;
			delete solve;
		}
		//若链表不是头结点,也就是头结点判断完毕,那就开始判断头结点后面的节点
		//先定义一个节点取代当前的头结点,因为都是采用指针进行操作,故修改其中的值,整个链表都会发生变化 
		ListNode* result=head;
		//这里的判断条件就是,当前节点不为空,当前节点的下一个节点也不为空,
		while (result!=NULL&&result->next!=NULL)
		{
			//如果当前节点的下一个节点的值等于val,那么就对其进行操作
			if (result->next->val == val)
			{
				ListNode* solve = result->next;
				result->next = solve->next;
				delete solve;
			}
			else//若不等于,就对其取代为下一个节点
			{
				result = result->next;
			}
		}
		return head;
	}
};
//解法二:
//设置一个虚拟头结点,也就是前面所述的设置一个头结点
class Solution {
public:
	ListNode* removeElements(ListNode* head, int val) {	
		//定义一个空链表
		ListNode* solve = new ListNode(0);
		solve->next = head;
		//将当前头指针赋予result
		ListNode* result = solve;
		while (result->next != NULL)
		{
			if (result->next->val == val)
			{
				ListNode* mid = result->next;
				result->next = mid->next;
				delete mid;
			}
			else {
				result = result->next;
			}
		}
		//循环结束,将头结点指向当前虚拟头结点所指向的指针方向
		head = solve->next;
		delete solve;
		return head;
		//最好是把所申请的内存进行删除,不然会造成内存泄露
	}
};

L707.设计链表https://leetcode.cn/problems/design-linked-list/submissions/

本题中,需要对链表进行结构体定义,也就是链表的初始化,并且在类中定义两个变量,虚拟头结点的val值可以什么都不放,但也可以放本链表的相关长度值(但需要注意是从0开始到size-1)

class MyLinkedList {
public:
    struct ListNode {
        int val;
        ListNode* next;
        ListNode(int val) :val(val), next(NULL){}
    };
    //构造函数,用来初始化MyLinkedList对象
    //这里定义的是虚拟头结点
    MyLinkedList() 
    {
        size = 0;
        Resulthead = new ListNode(0);
    }
    //找到下标为index的节点的值,下标无效则返回
    //也就是返回按照单列表的排序,index代表哪个链表,将他的值返回即可
    int get(int index) 
    {
        //看下标index是否比size大,或者小于0
        if (index > (size - 1) || index < 0)
        {
            return -1;
        }
        ListNode* solve = Resulthead->next;
        while (index--)
        {
            solve = solve->next;
        }
        return solve->val;
    }

    void addAtHead(int val) {
        ListNode* mid = new ListNode(val);
        mid->next = Resulthead->next;
        Resulthead->next = mid;
        //添加完之后 size要进行+1;
        size++;
    }

    void addAtTail(int val) {
        //定义一个val
        ListNode* mid = new ListNode(val);
        ListNode* cur = Resulthead;
        //现在来寻找当前链表的最后一个表格
        while (cur->next!=NULL)
        {
            cur = cur->next;
        }
        //已经找到最后一个链表,对其进行指针的交换即可
        cur->next = mid;
        size++;
    }

    void addAtIndex(int index, int val) {
        //如果相等,直接调用附加到最后一个的函数
        if (index < 0)
        {
            index = 0;
        }
        else if (index > size )
            return;
        ListNode* mid = new ListNode(val);
        ListNode* result = Resulthead;
        while (index--)
        {
            result = result->next;
        }
        mid->next = result->next;
        result->next = mid;
        size++;

    }

    void deleteAtIndex(int index) {
        if (index >= size || index < 0) {
            return;
        }
        ListNode* cur = Resulthead;
        while (index--) {
            cur = cur->next;
        }
        ListNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        size--;
    }


    //打印链表
    void printLinkedList() {
        ListNode* cur = Resulthead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    //每个对象中都有一个值,一个自定义指针
    int size;//代表链表的长度
    ListNode* Resulthead;//链表的头指针
};

L206.反转链表https://leetcode.cn/problems/reverse-linked-list/

本题一开始让我有点懵逼,也是采用的双指针对其进行翻转,但始终没有把逻辑理清楚,也就是一个快指针,一个慢指针,将快指针所指向的链表用一个中间变量存储起来,然后改变将快指针的指针指向慢指针,慢指针在等于快指针,相当于是一个交换标量,最好还是结合图一起来。

class Solution {
public:
	ListNode* reverseList(ListNode* head) {
		//先定义一个虚拟节点
		//先判断当前头节点是否为空,若为空直接返回
		if (head == NULL)return head;
		ListNode* cur = head;
		ListNode* pre = NULL;
		//ListNode* result = NULL;
		while (cur)
		{
			//先将当前节点指向的下一节点给一个节点存储起来
			ListNode* result = cur->next;
			cur->next = pre;
			pre = cur;
			cur = result;
		}
		return pre;
	}
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值