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

从0到1实现链表v1.0

0、CSDN Markdown目录使用须知

  • 如果你点击了目录↑跳转到一个不做所谓的页面,而导致看不到目录了,请点击浏览器的返回上一页,吐槽CSDN的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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值