机缘
很幸运能够成为csdn的一名博主。 一百天前, 我写了我的第一篇博客, 那是一篇自我介绍。 虽然已经忘记了当时的心情是好奇还是欣喜。 但是我很清楚当时我是不相信我能够一直进行创作, 并且收获这么多的粉丝的。 128天, 从当初刚刚学习c语言的分支与循环, 到如今已经学习到了c++的stl;从一开始没有粉丝,到今天我已经有了1900多的粉丝。我感觉真的很不可思议,仅仅不到半年我竟然能在编程的道路迈出了这么大的步子。
我在csdn创作的初心是记录学习的笔记,还有通过这种写博客, 自问自答的形式来解决编程之中比较复杂的知识点。基本上我在学习编程的过程中遇到的问题我都会写进博客, 然后通过写“为什么会这样呢?"然后使用vs进行调试。
记得有次在写到数组传参的时候,我突然想到函数的数组形参的本质是什么?当时我通过函数栈帧的知识点,我是知道形参是要进行压栈的, 所以我知道形参和实参是一个函数栈帧中的两块不同的空间。但是当时就想到为什么形参数组和实参数组明明是两块不同的空间, 为什么可以直接通过修改形参直接修改实参。 这个问题困扰了我好久,我还问过学校的老师, 但是学校的老师显然不相信我的理解能力, 不肯告诉我答案, 只是敷衍的告诉我——让我把形参和实参看成一个数组就行。 后来我还是通过vs的调试,以及sizeof对数组进行大小计算得出的结果, 原来形参数组本质上只是一个指针。
所以, 我创作博客就是一个在完善自身知识点,补全知识脉络的过程。 我认为我作品中所有写的知识都是我自己掌握的。即便现在没有掌握, 但我还在完善我的博客, 只要我在完善我的博客, 我总会复习我的博客之中的知识点,最终掌握它。
收获
说起创作csdn的收获,这就不得一下那些志同道合的“同行们”。
我在大概1000粉丝的时候认识了一群非常厉害的人, 他们有的占据着周榜前几, 有的几万粉丝, 有的隶属名校, 还有的已经步入社会, 参加工作。 每个人都是大佬,非常优秀。他们写的文章也很有深度, 至少我目前是看不得的。我很幸运能够认识到他们,让我认识到我与真正优秀的人之间的差距。这激励着我不辍修行。
当然, 创作获得得收获不可能仅仅如此, 创作的另一个好处当然就是收获了一批粉丝。到目前为止,我已经有了1900个粉丝。 这个数字是我一开始不敢想像的。 我一开始的目标就是我大学四年要获得3000粉丝。 然而不到半年的时间就完成了我一半以上的目标,真是令人欣喜。
对于我来说,还有一个很大的收获就是获得了一批复习笔记。每当我有些知识点记不得的时候, 我就会翻开我的博客进行查找。 就比如文件那一块很容易忘, 因为日常中很少用到——几乎不用。 也就容易忘。 而且这个笔记还能随时修改, 每次修改, 都会让这篇笔记更加充实, 更加完善。 我自己的知识网络和根基也会更加牢固。
日常
我现在的学习状态就是晚上十点以后总结过去的笔记,然后大概一周一篇博客。 这一篇博客我要通过基本上一天一个小时,一共一周时间进行整理。
然后平时的时间就是学习c++以及学校的课程了, c++前学到stl的哈希。已经学习了3/4,快要完结了。 c++的博客只是刚整理完类和对象。 当我学完c++的时候就要开始投入到整理知识点写博客中了。 这也是一个复习的过程。 我还是很期待整理知识点的时候的。 因为,c++的知识点很杂很多。 特例更多。 整理知识点会让我对c++的脉络有一个更好的掌握。
成就
我写的最有成就感的代码当属过去的几天写的红黑树插入操作。 并用红黑树对set和map进行了封装。红黑树我调试了很长一段时间, 当没有错误,完全跑出来的一刻, 很有成就感。
这也应该是我写过的难度最高的代码了吧。下面为我写的红黑树贴图。
#include<iostream>
using namespace std;
namespace cws
{
enum Colour
{
RED,
BLACK,
};
template<class T>
struct RBTreeNode
{
RBTreeNode* _left;
RBTreeNode* _right;
RBTreeNode* _parent;
T _data;//T的值用来插入, 那么k的值用来干什么呢?用来比较
Colour _col;
RBTreeNode(const T& val = T())
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _data(val)
, _col(RED)
{}
};
template<class T, class Ref, class Ptr>
struct __RBTree_iterator
{
typedef __RBTree_iterator<T, T&, T*> iterator;
typedef __RBTree_iterator<T, Ref, Ptr> self;
typedef RBTreeNode<T> node;
node* _node;
__RBTree_iterator(node* node)
:_node(node)
{}
__RBTree_iterator(const iterator& it)
:_node(it._node)
{}
Ref operator*()
{
return _node->_data;
}
Ptr operator->()
{
return &_node->_data;
}
self& operator++()
{
if (_node->_right != nullptr)
{
node* cur = _node->_right;
while (cur->_left != nullptr)
{
cur = cur->_left;
}
_node = cur;
}
else
{
node* cur = _node;
node* parent = cur->_parent;
while (parent != nullptr && cur == parent->_right)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
self& operator--()
{
if (_node->_left != nullptr)
{
node* cur = _node->_left;
while (cur->_left)
{
cur = cur->_left;
}
}
else
{
node* cur = _node;
node* parent = cur->_parent;
while (parent && cur == parent->_left)
{
cur = parent;
parent = parent->_parent;
}
_node = parent;
}
return *this;
}
bool operator!= (const self& it)
{
return it._node != _node;
}
};
template<class K, class T, class Compare>//这里的K其实就是一个不可修改的值, 之所以需要这个K就是因为要使用红黑树封装map, k是要进行比较的值。 但是可以使用K的值来进行比较。
class RBTree
{
typedef RBTreeNode<T> node;
public:
typedef __RBTree_iterator<T, T&, T*> iterator;
typedef __RBTree_iterator<T, const T&, const T*> const_iterator;
///iterator
iterator begin()
{
node* cur = _root;
while (cur != nullptr && cur->_left != nullptr)
{
cur = cur->_left;
}
return iterator(cur);
}
iterator end()
{
return iterator(nullptr);
}
///conductor//
RBTree()
:_root(nullptr)
{}
pair<iterator, bool> insert(const T& val)
{
node* newnode;
Compare com;
if (_root == nullptr)
{
_root = new node(val);
_root->_col = BLACK;
return pair<iterator, bool>(iterator(_root), true);
}
//
node* cur = _root;
node* parent = nullptr;
while (cur != nullptr)
{
if (com(val) > com(cur->_data))
{
parent = cur;
cur = cur->_right;
}
else if (com(val) < com(cur->_data))
{
parent = cur;
cur = cur->_left;
}
else
{
return pair<iterator, bool>(iterator(cur), false);
}
}
//找到节点,开始进行插入操作。 如果kv的值大于父亲的值, 那么就插在右边, 否则就插在左边。
cur = new node(val);
newnode = cur;
if (com(val) > com(parent->_data))
{
parent->_right = cur;
}
else
{
parent->_left = cur;
}
cur->_parent = parent;
//节点插入之后, 进行颜色判断,调整红黑树
while (parent && parent->_col == RED) //因为新插入的节点一定是一个红色节点, 所以如果父亲节点是红色的, 那么就要调整了。
{
//这里调整还有三种区别, 一种是如果叔叔存在且为红, 这个时候不需要进行旋转。
//第二种就是叔叔不存在或者存在但是为黑, 并且cur节点此时就在父亲节点的左边。 这个时候只需要进行单旋
//第三种就是叔叔不存在或者存在但是为红, 并且cur节点此时就在父亲节点的右边。 这个时候需要进行左右双旋
//首先第一件事是, 看一下父亲节点在爷爷节点的左边还是右边。 为了后续进行旋转。
node* grandparent = parent->_parent;
if (grandparent == nullptr)
{
break;
}
if (parent == grandparent->_left)
{
node* uncle = grandparent->_right;
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandparent->_col = RED;
cur = grandparent;//调整之后父亲节点如果存在, 那么父亲节点可能为红。 但是如果父亲节点不存在, cur就是根节点, 那么直接变黑。 如果父亲节点存在, 但是grandparent
//节点不存在, 那么父亲节点就一定是一个黑色节点。
parent = cur->_parent;
}
else
{
if (cur == parent->_left)
{
//单旋
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
//双旋
cur->_col = BLACK;
parent->_col = RED;
grandparent->_col = RED;
}
}
}
else//这是在左边的情况
{
node* uncle = grandparent->_left;
if (uncle && uncle->_col == RED)
{
uncle->_col = BLACK;
parent->_col = BLACK;
grandparent->_col = RED;
cur = grandparent;
parent = cur->_parent;
}
else
{
if (cur = parent->_right)
{
//单旋
parent->_col = BLACK;
grandparent->_col = RED;
}
else
{
//双旋
cur->_col = BLACK;
parent->_col = RED;
grandparent->_col = RED;
}
}
}
}//end of while
_root->_col = BLACK;
return pair<iterator, bool>(iterator(newnode), true);
}
void Inorder()
{
_Inorder(_root);
}
bool is_balance()
{
if (_root->_col == RED)
{
cout << "根节点的颜色为红" << endl;
return false;
}
int bechmark = 0;
node* cur = _root;
while (cur != nullptr)
{
if (cur->_col == BLACK)
{
bechmark++;
}
cur = cur->_left;
}
return _check(_root, 0, bechmark);
}
protected:
bool _check(node* root, int blackNum, int bechmark)
{
if (root == nullptr)
{
if (blackNum == bechmark)
{
return true;
}
else
{
cout << "每条路径的黑色节点数量不相等" << endl;
return false;
}
}
//
if (root->_col == RED && root->_parent && root->_parent->_col == RED)
{
cout << "存在连续的红色节点" << endl;
return false;
}
if (root->_col == BLACK)
{
blackNum++;
}
return _check(root->_left, blackNum, bechmark) && _check(root->_right, blackNum, bechmark);
}
void _Inorder(const node* root)
{
Compare com;
if (root == nullptr)
{
return;
}
//
_Inorder(root->_left);
cout << com(root->_data) << endl;
_Inorder(root->_right);
}
//左单旋
void RotateL(node* parent)
{
node* subR = parent->_right;
node* subRL = subR->_left;
parent->_right = subRL;
if (subRL != nullptr)
{
subRL->_parent = parent;
}
node* ppnode = parent->_parent;
parent->_parent = subR;
subR->_left = parent;
subR->_parent = ppnode;
if (ppnode != nullptr)
{
if (ppnode->_left == parent)
{
ppnode->_left = subR;
}
else
{
ppnode->_right = subR;
}
}
}
//右单旋
void RotateR(node* parent)
{
node* subL = parent->_left;
node* subLR = subL->_right;
parent->_left = subLR;
if (subLR != nullptr)
{
subLR->_parent = parent;
}
node* ppnode = parent->_parent;
parent->_parent = subL;
subL->_right = parent;
subL->_parent = ppnode;
if (ppnode != nullptr)
{
if (ppnode->_left == parent)
{
ppnode->_left = subL;
}
else
{
ppnode->_right = subL;
}
}
}
private:
node* _root;
};
}
憧憬
希望未来能过持续创作, 不松懈吧。短期的目标就是学习完c++, 然后将c++的专栏建立起来。 然后就开始linux的学习。至于长期的目标, 只是希望能够不忘初心, 不辍修行,专注于眼前。 多接触一些新事物, 不幻想, 不侥幸,保持行动力。 就这些吧!
记,我的128天创作纪念日