ColKang v1.0
/*
*2015.3.31 14:00更新
*上午刚写完这篇博客,下午就读到迭代器了。C++ primer中讲迭代器那节说道了->符号的意思,即(*ptr). 及将指针解引用之后再调用成员函数。这样一来理解就完全没有问题了,因为我定义collection *a; 实际上是定义了一个指针a,指向一个collection类
*所以在引用collection的成员函数时需要先解引用,得到a指针指向的collection类变量*a然后再调用它的成员函数。
*/
最近尝试写一下NFA到DFA转换的函数,用C++,但是想到集合的表示比较麻烦,一些高级的容器也还没学到,因此自己先写一个简单的collection类,1.0版本。
能实现的功能有:存储数字集合;能进行集合间比较O(N)及加O(M+N)减法O(N);能向集合中添加元素O(N)或删除元素O(N);能返回集合中第X小的元素O(1)
因为目前对C++理解较为有限,特别是写一个类的时候感到力不从心,因此很多地方应该都不是很符合规范,先将这个能实现基本功能的代码贴上来,再想一下以后的改进空间,之后写出更加完善的collection类。
/*
*ColKang v1.0
*这个类用来定义集合,因为未学到容器,因此自己写一个类来实现
*此类仅用于存储数字
*目前使用数组存储,可用跳跃表优化。
*/ #include<iostream>
using namespace std;
class collection
{
public:
//构造函数
collection()
{
for (int i = ; i < ; i++)
this->data[i] = ;
this->length = ;
}
//初始化集合
void init()
{
for (int i = ; i < ; i++)
this->data[i] = ;
this->length = ;
}
//判断两个集合是否相等
bool equal(collection *b)
{
if (this->length != b->length) return false;
else
{
for (int i = ;i < this->length;i++)
if (this->data[i] != b->data[i])
return false;
}
return true;
}
//得到集合的长度
void print_collection()
{
for (int i = ; i<this->length; i++)
cout << this->data[i] << ' ';
cout << endl;
}
int search_element(int b)
{
int i = , j = this->length - , mid = ;
while (i<j)
{
mid = (i + j) / ;
if (this->data[mid] == b) break;
else if (this->data[mid] > b) j = mid - ;
else i = mid + ;
}
if (i > j)
{
cout << "There is not a element that equals with " << b << "in this collection" << endl;
return -;
}
}
int get_length()
{
return this->length;
}
//得到集合中第X+1小的元素
int get_element(int x)
{
return this->data[x];
}
//集合添加元素,时间复杂度为O(N)
void add_element(int b)
{
int i = ;
while (this->data[i] <= b&&this->data[i] != -) i++;
for (int j = this->length - ; j >= i; j--)
this->data[j + ] = this->data[j];
this->data[i] = b;
this->length++;
}
//删除指定元素
void delete_element(int b)
{
int t;
if (t = this->search_element(b))
{
while (t < this->length - ) { this->data[t] = this->data[t + ]; t++; }
length--;
}
}
//进行集合加法
collection add_collection(collection *b)
{
//使用归并排序的合并部分
collection *c;
int i = , j = ;
while (i <= this->length && j <= b->length)
{
c->length++;
if (this->data[i] = b->data[j]) j++;
else if (this->data[i] < b->data[j]) c->data[c->length] = this->data[i];
else c->data[c->length] = b->data[j];
}
if (i <= this->length)
while (i <= this->length)
{
c->length++;
c->data[c->length] = this->data[i];
i++;
}
else
while (j <= b->length)
{
c->length++;
c->data[c->length] = b->data[j];
}
return *c;
}
//集合减法
void sub_collection(collection *b)
{
//对每个b集合中的元素调用delete_element
for (int i = ; i<b->length; i++)
this->delete_element(b->data[i]);
}
private:
int data[], length;
};
其中用到的一些小方法:search_element(int x)使用了二分查找,使查找的复杂度降低到O(lgn),集合加法使用了归并排序中的合并部分,实现了O(M+N)而不是N次插入。
遇到的困难:其实还挺多的,第一次写类,感觉好多地方都不太懂。
1.最开始的时候所有的->都用.来表示,因为我记得语法中是这么来引用成员函数或者成员变量的,但是后来vs报错,又去网上查了一下才知道,原来如果这个类定义的时候是指针:collection *p ,那么引用成员函数及成员变量的时候是需要用->来引用的,如果定义的时候是collection p,那么直接使用.就可以了。而我发现因为各个地方都要传参数进去,出于方便考虑就是用了指针的方式。
2.add_collection函数。首先是this指针,之前C++课程开设的时候就对this指针理解的比较模糊,只记得它是指向当前对象,对于一个类来说就是指这个类。我在写add_collection函数的时候,最初是这么写的: collection * add_collection(collection*a.collection*b),后来想到一个问题:这个函数是collection的成员函数,那么调用的时候就得用 collection *collectionAns = collectionA.add_collection(*collectionA,*collectionB)这么蛋疼的方式,而且collectionA是必定要参与运算的,那么为什么还要多此一举使用两个参数呢,因此就改成了只有一个参数的函数。与是就成了collection *collectionAns = collectionA.add_collection(*collectionB)。然后又想了一下,感觉可以把返回值去掉(当时考虑的是既然this指向的就是这个类,那么只要让this指向加法产生后的结果不就可以了)结果vs继续报错,查了一下说是this指针指向的位置是固定的,不能以任何方式更改。这个道理仔细想了一下,确实是一个很合理的规定,与是就沿用了上面的方式,但是因为我想让集合a和b的加和结果存在a中,与是现在调用就成了a = a.add_collection(*b);如果要把结果存在第三个集合中,就是一种更为纠结的方式:collection *c = a.add_collection(*b)。后来想了一下,能否把函数add_collection写在collection类的外面呢?但是因为这个类中调用了collection类的私有成员变量,写在外面是无法调用到这些变量的,因此就只能做到目前这样了,感觉C++不会留这样纠结的方式吧~以后等学到能解决这些问题的地步再来重写这个函数。
基本就是这两个问题让我最为头大,其他小问题也多多少少出现了不少,感觉语法还是最为基础也是最需要掌握好的,不然第一个问题.和->就不会困扰我那么久了(之前报错从来没想过是这个的问题~_~)
目前优化的方向来讲,主要有这几个方面吧:
1.存储的方式。现在是数组存储,因为考虑到如果用链表的话不能直接获取下标,这样get_element(int x)函数的时间复杂度会变成0(N),而且我个人对C++指针部分学习还不是很到位。以后拟使用跳跃表来存储,并稍作调整:每一个非底层链表中存有一个域指出当前元素在最底层链表中的位置,这样add_collection,sub_collection,add_element,这几个元素的时间复杂度都会有提升,而且search_element的时间复杂度也会比较理想(应该是O(sqrt(n),当时看跳跃表的时候记得高度是sqrt(n),底层链表中每个区间长度期望值也是sqrt(n))
2.扩展集合的类型。现在只支持数字,希望能以后扩展到字母,符号,再深入一点扩展到数组,字符串,甚至类。
3.运算符重载。这个我目前只是理解一个概念,但是并未深入,如果能弄好这个,我感觉那个add_collection函数的蛋疼之处就能解决掉啦~
ColKang v1.0的更多相关文章
- Git异常:fatal: V1.0 cannot be resolved to branch.
GitHub实战系列汇总:http://www.cnblogs.com/dunitian/p/5038719.html ———————————————————————————————————————— ...
- 自己动手写计算器v1.0
今天突发奇想,想着看了还几个设计模式了,倒不如写点东西来实践它们.发现计算器这种就比较合适,打算随着设计模式的学习,会对计算器不断的做改进. 包括功能的增加和算法的改进.初学者难免犯错,希望大家不吝指 ...
- ASP.NET Boilerplate终于发布v1.0了
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:ABP经过2年多的开发,终于发布第一个主要版本了,谨此提醒ABP的使用者. ASP.N ...
- 【JS】heatmap.js v1.0 到 v2.0,详细总结一下:)
前段时间,项目要开发热力图插件,研究了heatmap.js,打算好好总结一下. 本文主要有以下几部分内容: 部分源码理解 如何迁移到v2.0 v2.0官方文档译文 关于heatmap.js介绍,请看这 ...
- 图像处理工具V1.0
图像处理工具V1.0(仿彗星图片处理工具.VS2015安装界面)----个人无聊作品 以下是界面: 部分代码一.(摘自网络----加水印代码): public static void ImageWat ...
- reGeorg v1.0内网流量转发
reGeorg v1.0 git Usage $ reGeorgSocksProxy.py [-h] [-l] [-p] [-r] -u [-v] Socks server for reGeorg H ...
- 【原创】风讯DotNetCMS V1.0~V2.0 SQL注入漏洞
文章作者:rebeyond 注:文章首发I.S.T.O信息安全团队,后由原创作者友情提交到乌云-漏洞报告平台.I.S.T.O版权所有,转载需注明作者. 受影响版本:貌似都受影响. 漏洞文件:use ...
- 屏幕监视专家 v1.0 定时录制屏幕动画发送到指定邮箱
ScreenWatcher v1.0功能:定时录制屏幕动画发送到指定邮箱,录制的动画为gif,可指定录制多长时间.指定几点直接开始录制,完全后台运行.作者:Bluefish 下载链接: http:// ...
- 03-c#入门(简易存款利息计算器v1.0)
本想把练习题做了的结果放上来,不过发现附录是有答案的,就算了吧,自己做了没问题就行了哈.之前提到过,要是有朋友有想法,需要做小工具我可以帮忙实现,不过貌似大家都很忙.SO,自己学完第4章后,决定做一个 ...
随机推荐
- Storm程序永久代内存溢出
在集群中部署Storm应用程序的时候报错,并通过jdk自带的jconsole监控发现,永久代内存瞬间爆炸了 org.springframework.beans.factory.BeanCreation ...
- list_for_each_entry解析
双向链表及链表头: 建立一个双向链表通常有一个独立的用于管理链表的链表头,链表头一般是不含有实体数据的,必须用INIT_LIST_HEAD()进行初始化,表头建立以后,就可以将带有数据结构的实体链表成 ...
- Way to MongoDB
1.MongoDB术语/概念:database,collection,document,field,indexSQL术语/概念:database,table,row,column,index 2.所有 ...
- JavaScript:学习笔记(9)——Promise对象
JavaScript:学习笔记(9)——Promise对象 引入Promise Primose是异步编程的一种解决方案,比传统的解决方案回调函数和事件更加合理和强大.如下面为基于回调函数的Ajax操作 ...
- Python-argparse-命令行与参数解析
import argparse import numpy as np import cv2 import os import numpy.random as npr from dface.core.u ...
- HDU - 4675 GCD of Sequence (莫比乌斯反演+组合数学)
题意:给出序列[a1..aN],整数M和k,求对1-M中的每个整数d,构建新的序列[b1...bN],使其满足: 1. \(1 \le bi \le M\) 2. \(gcd(b 1, b 2, -, ...
- kivy sdl2 - ImportError: DLL load failed: 找不到指定的模块
from kivy.app import App from kivy.uix.button import Button class TestApp(App): def build(self): ret ...
- C++中去掉string字符串中的\r\n等
string imagedata;imagedata = “dudau\r\ndadafca\r\n” CString Image; Image = imagedata.c_str(); Image. ...
- C++——创建类的时候用new与不用new 的区别
转自:https://www.cnblogs.com/tony-li/p/4111588.html C++在创建对象的时候可以采用两种方式:(例如类名为Test) Test test 或者 Test ...
- [Android] 录音与播放录音实现
http://blog.csdn.net/cxf7394373/article/details/8313980 android开发文档中有一个关于录音的类MediaRecord,一张图介绍了基本的流程 ...