Day3 移除链表元素 设计链表 翻转链表

移除链表元素

#include<iostream>
using namespace std;
struct linknote
{
	int val;
	linknote* next;
linknote(int x) :next(nullptr), val(x)
{

}
};
void shanchu(linknote* start,int target)
{
	linknote* p = new linknote(0);
	p->next = start;
	if (start == nullptr)
	{
		cout << "nothing没有元素" << endl;
		return;
	}
	while (p->next != nullptr)
	{
		if (p->next->val == target)
		{
			p->next = p->next->next;//我认为这个地方最好的理解方式就是前值后  让左面的值指向右面的值
			
			break;
		}
		else
		{
			p = p->next;
		}
	}


}
void xianshi(linknote* start2)
{
	while (start2 != nullptr)
	{
		cout << start2->val << " ";
	}
}
int main()
{
	linknote* p1 = new linknote(3);
	linknote* p2 = new linknote(4);
	linknote* p3 = new linknote(5);
	p1->next = p2;
	p2->next = p3;
	shanchu(p1,3);
	xianshi(p1);
}
///* 删除链表的节点 n0 之后的首个节点 */
//void remove(ListNode* n0) {
//	if (n0->next == nullptr)
//		return;
//	// n0 -> P -> n1
//	ListNode* P = n0->next;
//	ListNode* n1 = P->next;
//	n0->next = n1;
//	// 释放内存
//	delete P;
// 
// ListNode* P ;
// n0->next;=p;
// 
//}

在链表操作中,直接覆盖节点值并不等于删除节点。删除节点不仅需要从链表中移除,还需要正确释放其内存,以防止内存泄漏

正确的做法是在移动指针之前保存当前节点的指针,然后在移动指针之后删除当前节点。

shanchu 函数中,不需要删除 cur 的原因是 cur 只是一个指向链表中某个节点的指针变量,它本身并不占用动态内存。我们只需要删除动态分配的节点,指针变量 cur 是局部变量,会在函数结束后自动销毁,不需要手动删除。

这里的 linknote*& start 表示传递的是 linknote* 类型的引用,即指针的引用。

#include<iostream>
using namespace std;
struct linknote
{
	linknote* next;
	int val;
	linknote(int x):next(nullptr),val(x){}
};
void shanchu(linknote* &start, int target)
{
	linknote* p = new linknote(0);
	p->next = start;
	linknote* cur = p;
	while (cur->next != nullptr)
	{
		if (cur->next->val == target)
		{
			linknote* temp = cur->next;
			cur->next = cur->next->next;
			delete temp;
			break;
		}
		else
		{
			cur = cur->next;
		}
	}
	start = p->next;
	delete p;
}
void xianshi(linknote* start2)
{
	while (start2 != nullptr)
	{
		cout << start2->val << " ";
		start2 = start2->next;
	}
}
int main()
{
	linknote* p1 = new linknote(3);
	linknote* p2 = new linknote(4);
	linknote* p3 = new linknote(5);
	p1->next = p2;
	p2->next = p3;
	xianshi(p1);
	shanchu(p1, 3);
	cout << endl;
	xianshi(p1);
	

	while (p1!=nullptr)
	{
		linknote* temp = p1;
		p1 = p1->next;
		delete temp;
	}

}

我个人认为还是应该写带虚拟头节点的,这样更方便做一些处理。

设计链表

以下这个报错是设计链表里面的

一下这个代码虽然错误百出  但是只有知道每一步的错误原因,才能更好的理解链表。

这个代码的具体找错,我会在以后在小红书上学习直播的时候讲 

#include<iostream>
using namespace std;
struct linknote
{
	linknote* next;
	int val;
	linknote(int x) :next(nullptr), val(x) {}
};
int re_long(linknote* start)
{
	int l_ong = 0;

	while (start != nullptr)
	{
		l_ong++;
		start = start->next;
	}
	return l_ong;
}
void  get(int index, int n, linknote* start)
{
	if (index<0 || index>n)
	{
		cout<< "不符合查询范围";
		return;
	}
	while (index--)
	{
		start = start->next;
	}
	cout << start->val;

}
void addbegin(linknote*& start, int vall)
{
	linknote* cur = new linknote(vall);
	cur->next = start;
	while (cur != nullptr)
	{
		cout << cur->val << " ";
		cur = cur->next;
	}
	//delete cur;在你最初的代码中,是在打印链表节点后删除 cur 指针的,
	// 但是由于在打印链表节点时,cur 指针已经指向了链表中的下一个节点,所以实际上你并没有删除链表的头节点,
	// 而是删除了链表的第二个节点,这样会导致链表头节点丢失,无法正确访问整个链表。
}
void addend(linknote*& start, int vall)
{
	linknote* cur = new linknote(vall);
	//if (start == nullptr)
	//{
	//	start= cur;
	//	return;
	//}
	linknote* note = start;

	while (note->next != nullptr)
	{
		note = note->next;
	}
	note->next = cur;
	while (start != nullptr)
	{
		cout << start->val << " ";
		start = start->next;
	}

}
void tianjia(linknote*& start, int index, int n,int vall)
{
	if (index == n)
	{
		addend(start, vall);
	}
	else if (index > n)
	{
		cout << "impossible";
	}
	else if (index < 0)
	{
		addbegin(start, vall);
	}
	else
	{
		linknote* cur = start;
		
	/*	while (index--)
		{
			cur = cur->next;
		}*/
		for (int i = 0; i < index; ++i)
		{
			if (cur == nullptr || cur->next == nullptr) {
				cout << "Error: n is out of bounds of the list length." << endl;
				return; // Exit the function or handle the error as needed
			}
			cur = cur->next;
		}
		linknote* cha = new linknote(vall);
		cha->next = cur->next;
		cur->next = cha;
		while (start != nullptr)
		{
			cout << start->val << " ";
			start = start->next;
		}
	
		linknote* cur = start;

		// 遍历链表到指定索引位置
		for (int i = 0; i < index; ++i)
		{
			if (cur == nullptr || cur->next == nullptr) {
				cout << "Error: index is out of bounds of the list length." << endl;
				return; // 退出函数或按需处理错误
			}
			cur = cur->next;
		}

		linknote* cha = new linknote(vall);
		cha->next = cur->next;
		cur->next = cha;

		// 使用临时指针打印链表,避免修改 start
		linknote* temp = start;
		while (temp != nullptr)
		{
			cout << temp->val << " ";
			temp = temp->next;
		}

	}
}
void shanchu(linknote*& start, int index,int n)
{
	if (index > n || index < 0)
	{
		cout << "impossible";
	}
	else
	{
		linknote* cur = start;
		while (index--)
		{
			cur = cur->next;
		}
		cur = cur->next;
	}
	while (start != nullptr)
	{
		cout << start->val << " ";
		start = start->next;
	}
}
void shanchu(linknote*& start, int index, int n)
{
	if (index >= n || index < 0)
	{
		cout << "impossible" << endl;
		return; // 立即返回避免继续执行
	}

	linknote* cur = start;
	 //如果要删除的是第一个节点
	if (index == 0)
	{
		linknote* toDelete = start;
		start = start->next;
		delete toDelete;
	}
	else
	{
		// 遍历到 index 位置的前一个节点
		for (int i = 0; i < index - 1; ++i)
		{
			cur = cur->next;
		}
		// 删除节点
		linknote* toDelete = cur->next;
		cur->next = cur->next->next;
		delete toDelete;
	}

	// 使用临时指针打印链表,避免修改 start
	linknote* temp = start;
	while (temp != nullptr)
	{
		cout << temp->val << " ";
		temp = temp->next;
	}
cout << endl; // 输出换行符
}

int main()
{
	linknote* p1 = new linknote(2);
	linknote* p2 = new linknote(3);
	linknote* p3 = new linknote(4);
	p1->next = p2;
	p2->next = p3;
	int n = re_long(p1);
	cout << "get" << endl;
	get(1, n, p1);
	cout << endl << "begin" << endl;
	addbegin(p1, 1);
	cout << endl << "end" << endl;
	addend(p1, 6);
	cout << "tianjia" << endl;
	//tianjia(p1, 1, n, 0);
	cout << endl << " shanchu" << endl;
	/*shanchu(p1, 3, n);*/


}

 请仔细看下面这个再类中又用到了结构体

 这个是标准答案

#include <iostream>
using namespace std;

class MyLinkedList {
public:
    // 定义链表节点结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val) : val(val), next(nullptr) {}
    };

    // 初始化链表
    MyLinkedList() {
        _dummyHead = new LinkedNode(0); // 这里定义的头结点是一个虚拟头结点,而不是真正的链表头结点
        _size = 0;
    }

    // 获取到第index个节点数值,如果index是非法数值直接返回-1,注意index是从0开始的,第0个节点就是头结点
    int get(int index) {
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while (index--) { // 如果--index 就会陷入死循环
            cur = cur->next;
        }
        return cur->val;
    }

    // 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点
    void addAtHead(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }

    // 在链表最后面添加一个节点
    void addAtTail(int val) {
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }

    // 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。
    // 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点
    // 如果index大于链表的长度,则返回空
    // 如果index小于0,则在头部插入节点
    void addAtIndex(int index, int val) {
        if (index > _size) return;
        if (index < 0) index = 0;
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while (index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }

    // 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的
    void deleteAtIndex(int index) {
        if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while (index--) {
            cur = cur->next;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        //delete命令指示释放了tmp指针原本所指的那部分内存,
        //被delete后的指针tmp的值(地址)并非就是NULL,而是随机值。也就是被delete后,
        //如果不再加上一句tmp=nullptr,tmp会成为乱指的野指针
        //如果之后的程序不小心使用了tmp,会指向难以预想的内存空间
        tmp = nullptr;
        _size--;
    }

    // 打印链表
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != nullptr) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }

private:
    int _size;
    LinkedNode* _dummyHead;
};

int main() {
    MyLinkedList linkedList;

    linkedList.addAtHead(1);
    linkedList.printLinkedList(); // 输出: 1

    linkedList.addAtTail(3);
    linkedList.printLinkedList(); // 输出: 1 3

    linkedList.addAtIndex(1, 2);  // 链表变为1->2->3
    linkedList.printLinkedList(); // 输出: 1 2 3

    cout << linkedList.get(1) << endl; // 返回2

    linkedList.deleteAtIndex(1);  // 现在链表是1->3
    linkedList.printLinkedList(); // 输出: 1 3

    cout << linkedList.get(1) << endl; // 返回3

    return 0;
}

 

反转链表

其中注释处是错误的,要是想加深以下理解,可以来我的直播间,大家一起学习!!!

#include<iostream>
using namespace std;
struct linknote
{
	linknote* next;
	int val;
	linknote(int x):next(nullptr),val(x){}
};
//void fanzhuan(linknote*&start)
//{
//	linknote* cur = start;
//	linknote* temp = cur->next;
//	while (temp!= nullptr)
//	{
//		temp->next = cur;
//		cur = temp;
//		temp = temp->next;
//		
//	}
//	while (start != nullptr)
//	{
//		cout << start->val << " ";
//		start = start->next;
//	}
//}   这个代码虽然错了 但是你可以去找错 并改正  可以提高自己
void fanzhuan(linknote* start)
{
	linknote* pre = nullptr;
	linknote* cur = start;
	linknote* temp;
	while (cur!=nullptr)
	{
		temp = cur->next;//这个相当于是赋值
		cur->next = pre;//这个相当于改变指针的指向
		pre = cur;
		cur = temp;
	}
	start = pre;//这个地方前方别忘了  相当于是反转了
		while (start != nullptr)
	{
		cout << start->val << " ";
		start = start->next;
	}
}
int main()
{
	linknote* p1 = new linknote(3);
	linknote* p2 = new linknote(4);
	linknote* p3 = new linknote(5);
	linknote* p4 = new linknote(6);
	p1->next = p2;
	p2->next = p3;
	p3->next = p4;

	fanzhuan(p1);
}

小红书直播

为了能让大家更好的了解数据结构,大家可以关注我的小红书直播,欢迎大家一起进步,一起学习算法!我会在7.11号之后开课,希望能和大家一起讨论!!!

  • 16
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是链表元素的Python代码: ```python class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def removeElements(head: ListNode, val: int) -> ListNode: # 处理头部节点为要删除元素的情况 while head is not None and head.val == val: head = head.next # 处理链表中间节点为要删除元素的情况 if head is not None: node = head while node.next is not None: if node.next.val == val: node.next = node.next.next else: node = node.next return head ``` 这里定义了一个ListNode类表示链表节点,其中val表示节点的值,next表示指向下一个节点的指针。removeElements函数的第一个参数head表示链表的头节点,第二个参数val表示要删除的元素值。函数的返回值是除后的链表头节点。 函数的实现分为两步: 1. 处理头部节点为要删除元素的情况,即如果头部节点的值等于要删除的元素值,则将头部节点指向下一个节点,直到头部节点的值不等于要删除的元素值。 2. 处理链表中间节点为要删除元素的情况,即从头节点开始遍历链表,如果当前节点的下一个节点的值等于要删除的元素值,则将当前节点的next指针指向下一个节点的next指针,即跳过当前节点的下一个节点;否则,将当前节点指向下一个节点。遍历完成后,返回链表的头节点。 注意,这里的实现并没有考虑链表为空的情况,需要在调用函数前进行判断。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值