算法001-C++从0到1实现链表v1

本文详细介绍了如何从零开始实现单向链表,并包含了基本的链表操作如构造、获取节点个数、判断是否为空、尾部插入和删除、链表反转以及输出链表。同时,讨论了待优化和扩展的部分,如增加清零、析构、指定位置的增删、排序和查找功能,以及考虑将链表转换为双向链表以提高效率。

从0到1实现链表v1.0

0、优快云 Markdown目录使用须知

  • 如果你点击了目录↑跳转到一个不做所谓的页面,而导致看不到目录了,请点击浏览器的返回上一页,吐槽优快云的markdown支持*2
  • 三月份的时候还挺不好用的,但是六月份就好了,奇奇怪怪。
  • 我还想给我的markdown每一个章节末尾插入一个跳转至目录的按钮,不知道怎么加。当然咯,你也可以使用home键返回文章开头,就可以返回目录了。

1、版本概览

  • 这是一个单向链表,带头尾指针;
  • 目前实现的成员函数比较少:构造,获取节点个数,判空,尾插,尾删,链表逆转,输出链表;

2、待扩展,更新,优化的部分

  • 还需增加:清零,析构,指定位置增、删,排序(话说适合链表的排序算法有几种啊?),查找(极其愚笨的低效查找,链表是否有序都不影响它的低效性);
  • 还需优化:
    • 写成类模板,以此获得更好的复用;
    • 整体重写成双向链表,实现的尾删那一个成员函数,可以由O(n)变成O(1),巨大的时间复杂度的提升;
    • 把每个函数拆分cpp编写,会变得更容易查看;
    • 话说,如果写成了类模板,又做了cpp的拆分,似乎要全部写成hpp,否则在 类模板的 二次编译的 问题上 会出错;

3、参考致谢

  • 这么粗糙的版本参考谁,都算得上是对原作者的侮辱
  • 本人(陈澈)纯手打,练手

4、源代码

#include<iostream>
using namespace std;

//节点结构体
struct Node {
	int data;
	Node* next;
};

//带头尾指针的单链表,缺点:查找上一项困难,删除尾节点困难
class List {
private:
	Node* head;
	Node* tail;
	int size;
public:
	List();
	//~List();
	int getsize() { return size; }
	bool isEmpty();
	void insertLast(int elemnt);
	int popLast();//及其低效
	int reverse();
	void show();
};

//构造
List::List() {
	head = NULL;
	tail = NULL;
	size = 0;
}

//List::~List() {
	//怎么样析构掉这个链表呢?,先实现insert再说吧
	//把insert里面new的那些玩意儿都给delete掉
//}

//判空
bool List::isEmpty() {
	return head == NULL;
}

//尾插
void List::insertLast(int elemnt) {
	Node* node = new Node;
	node->data = elemnt;
	node->next = NULL;

	if (this->isEmpty()) {//当node以第一个元素插入的时候
		//等效写法:this->isEmpty()  <==>  NULL == tail
		head = node;
		tail = node;
	}
	else {//当node以非第一个元素插入的时候
		Node* temp = tail;
		tail = node;
		temp->next = node;
	}
	size++;
}

//尾删。极其低效O(n),强烈建议用少量空间换取时间,加上一个指针域,变成双向链表
int List::popLast() {
	//原本一个节点都没有
	if (this->isEmpty())
		return -1;//删除失败,已经没节点了
	//如果只有一个节点了
	else if (NULL == head->next) {
		Node* temp = tail;
		head = NULL;
		tail = NULL;
		delete temp;
		return 0;
	}
	//否则,有一个以及以上的节点
	else {
		//靠,单向链表删除最后一个节点,尾指针怎么样指向倒数第二额个指针,是个问题呀
		//不用想了,从头开始遍历,至结尾,低效,所以最好还是写成双向链表
		//如果poplast是一个高频操作,重构整个链表势在必行
		Node* last = tail;
		Node* temp = head, *tempnext = head->next;
		while (true) {
			if (tempnext->next == NULL)
				break;//此刻的temp就是倒数第二个节点
			temp = tempnext;
			tempnext = tempnext->next;
		}
		tail = temp;
		temp->next = NULL;
		delete last;
		return 0;
	}
}

//逆转链表
int List::reverse() {
	//当没有节点的情况
	if (isEmpty())
		return 0;
	//有一个节点的情况
	Node* p1 = head;
	if (NULL == p1->next)
		return 0;
	//当有两个节点或者以上的情况
	Node* p2 = p1->next;
	Node* p3 = p2->next;
	p1->next = NULL;
	tail = p1;//这一句差点漏了,一个容易修补的小bug,20190316
	while (true) {
		p2->next = p1;
		if (NULL == p3) {
			head = p2;
			break;
		}
		p1 = p2; p2 = p3; p3 = p3->next;
	}
	return 0;
}

//打印链表
void List::show() {
	Node* temp = head;
	if (this->isEmpty()) {
		cout << "链表为空" << endl;
		return;
	}
	while (true) {
		if (temp->next == NULL) {
			cout << temp->data << ' ' << "链表结束" << endl;
			break;
		}
		cout << temp->data << ' ';
		temp = temp->next;
	}
	cout << "head=" << head->data << ' '
		<< "tail=" << tail->data << endl;
	return;
}

//这是一个测试函数
void test1() {
	List li;
	cout << li.getsize() << endl;
	li.insertLast(1);
	li.insertLast(2);
	li.insertLast(3);
	li.insertLast(4);
	cout << li.getsize() << endl;
	li.show();
	li.reverse();
	li.show();
}

int main()
{
	test1();
	system("pause");
	return 0;
}
【电能质量扰动】基于ML和DWT的电能质量扰动分类方法研究(Matlab实现)内容概要:本文研究了一种基于机器学习(ML)和离散小波变换(DWT)的电能质量扰动分类方法,并提供了Matlab实现方案。首先利用DWT对电能质量信号进行多尺度分解,提取信号的时频域特征,有效捕捉电压暂降、暂升、中断、谐波、闪变等常见扰动的关键信息;随后结合机器学习分类器(如SVM、BP神经网络等)对提取的特征进行训练与分类,实现对不同类型扰动的自动识别与准确区分。该方法充分发挥DWT在信号去噪与特征提取方面的优势,结合ML强大的模式识别能力,提升了分类精度与鲁棒性,具有较强的实用价值。; 适合人群:电气工程、自动化、电力系统及其自动化等相关专业的研究生、科研人员及从事电能质量监测与分析的工程技术人员;具备一定的信号处理基础和Matlab编程能力者更佳。; 使用场景及目标:①应用于智能电网中的电能质量在线监测系统,实现扰动类型的自动识别;②作为高校或科研机构在信号处理、模式识别、电力系统分析等课程的教学案例或科研实验平台;③目标是提高电能质量扰动分类的准确性与效率,为后续的电能治理与设备保护提供决策依据。; 阅读建议:建议读者结合Matlab代码深入理解DWT的实现过程与特征提取步骤,重点关注小波基选择、分解层数设定及特征向量构造对分类性能的影响,并尝试对比不同机器学习模型的分类效果,以全面掌握该方法的核心技术要点。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值