甲:我想重温一下数据结构,你有什么好办法?
乙: stackoveflow 不错的哇, 比如,有个叫 Nakul Chaudhary 的哥们在上面的 data structre 的标签中问:在大多数编程语言中,字典较之哈希表都要受欢迎,这之后的原因是什么(In most of programming languages, dictionaries are preferred over hashtables. What are the reasons behind that?)
甲:等等,好像是哈希表较之字典有用啊。
乙:先听听他们怎么说的?提问者录用的答案是 Michael Madsen 回答的:
FWIW, a Dictionary is a hash table.
If you meant "why do we use the Dictionary class instead of the Hashtable class?", then it's an easy answer: Dictionary is a generic type, Hashtable is not. That means you get type safety with Dictionary, because you can't insert any random object into it, and you don't have to cast the values you take out.
那要看你怎么说了,字典也是一个哈希表。如果你的回答是“我们为什么用字典类来取代 Hashtable 类”,答案就容易了:Dictionary 是泛型,哈希表不是。那就意味你用字典获得了安全性,这是因为你不能在字典中插入任何随机对象,而且你也不可以 cast 你取出来的值。
甲:好像明白,可哈希表不是线程安全的,还用字典啊?
乙:先看另一个回答:
Coming to difference between HashTable
& Dictionary
, Dictionary
is generic where asHastable
is not Generic. We can add any type of object to HashTable
, but while reteriving we need to Cast it to the required Type(我们可以给 HashTable 添加任何对象,但在检索时就需要将其 Cast 成所需的类型). So, it is not type safe(所以哈希不是类型安全的). But to dictionary
, while declaring itself we can specify the type of Key & Value, so no need to cast while retreiving. Let's take an Example,
HashTable
class HashTableProgram
{
static void Main(string[] args)
{
Hashtable ht = new Hashtable();
ht.Add(1, "One");
ht.Add(2, "Two");
ht.Add(3, "Three");
foreach (DictionaryEntry de in ht)
{
int Key = (int)de.Key; //Casting
string value = de.Value.ToString(); //Casting
Console.WriteLine(Key + " " + value);
}
}
}
关于Dictionary,
class DictionaryProgram
{
static void Main(string[] args)
{
Dictionary<int, string> dt = new Dictionary<int, string>();
dt.Add(1, "One");
dt.Add(2, "Two");
dt.Add(3, "Three");
foreach (KeyValuePair<int, String> kv in dt)
{
Console.WriteLine(kv.Key + " " + kv.Value);
}
}
}
比如又有一哥们 Anton Kazennikov 问:
Is there any speed- and cache-efficient implementations of tree in C/C++? I know what a tree is, but I don't want reinvent the wheel, implementing it myself.
这哥们知道什么是树,但询问有什么方法来快速的实现 C/C++ 中的树。
录用的是 SashaN 哥们的回答:
if you are looking for an ANSI C implementation you can "steal" it from FreeBSD. The file you are looking for is called radix.c. It's used for managing routing data in kernel.
如果你是在询问ANSI C 版本的实现,你就可以从FreeBSD 那里“借鉴”。你要看的文件就叫做 radix.c. 这个 C 文件是用来管理 Radix tree 的。
甲:好吧,我知道是一颗很复杂的树。我看到这样一个问题,sdellysse 哥们问的:
I've always been one to simply use List<String> names = new ArrayList<String>();
I use the interface as the type name for portability, so that when I ask questions such as these I can rework my code.
When should LinkedList
be used over ArrayList
and vice-versa?
他总是 new 出一个 ArrayList<String>类型的变量,用这种类型作为接口名,方便修改其中的代码,他问道:什么时候应当使用 LinkedList
来申明而非 ArrayList
,反之亦然。
甲:这容易回答, ArrayList
数组列表, LinkedList
链接列表,元素是安图索骥这样插入删除的就用 LinkedList
, 否则就用 ArrayList
,是么?
乙:看看他录用的答案是怎么说的 --
LinkedList and ArrayList are two different implementations of the List interface.( List 接口的两种不同实现 ) LinkedList implements it with a doubly-linked list. ArrayList implements it with a dynamically resizing array.
LinkedList allows for constant-time insertions or removals, but only sequential access of elements.(LinkedList 允许你在常量时间内插入或删除,但只能一步步顺着链接的存储点来) In other words, you can walk the list forwards or backwards, but grabbing an element in the middle takes time proportional to the size of the list.
ArrayLists, on the other hand, allow random access, so you can grab any element in constant time. But adding or removing from anywhere but the end requires shifting all the latter elements over, either to make an opening or fill the gap. Also, if you add more elements than the capacity of the underlying array, a new array (twice the size) is allocated, and the old array is copied to the new one, so adding to an ArrayList is O(n) in the worst case but constant on average.
So depending on the operations you intend to do, you should choose the implementations accordingly. Iterating over either kind of List is practically equally cheap. (Iterating over an ArrayList is technically faster, but unless you're doing something really performance-sensitive, you shouldn't worry about this -- they're both constants.)
Also, if you have large lists, keep in mind that memory usage is also different. Each element of a LinkedList has more overhead since pointers to the next and previous elements are also stored. ArrayLists don't have this overhead. However, ArrayLists take up as much memory as is allocated for the capacity, regardless of whether elements have actually been added.
The default initial capacity of an ArrayList is pretty small (10 from Java 1.4 - 6). But since the underlying implementation is an array, the array must be resized if you add a lot of elements. To avoid the high cost of resizing when you know you're going to add a lot of elements, construct the ArrayList with a higher initial capacity.
It's worth noting that Vector also implements the List interface and is almost identical to ArrayList. The difference is that Vector is synchronized, so it is thread-safe. Because of this, it is also slightly slower than ArrayList. So as far as I understand, most Java programmers avoid Vector in favor of ArrayList since they will probably synchronize explicitly anyway if they care about that.
甲:不就一个 线性表的顺序存储结构和链式存储结构?乙:恩,但正真的工程师注重的都是细节。
甲:By the way , 换个话题, 现在有各种网络课堂, 比如
网易云课堂 ,他的喊话是:万事皆有可学,事事皆有学文;
百度介绍:
网易云课堂教育平台是网易公司研发的一款大型在线教育平台服务,该平台面向学习者提供海量免费、优质课程,创新的个性化学习体验,自由开放的交流互动环境。继网易公开课后,网易云课堂是网易公司在教育领域的又一重量级产品。
YY教育,他的 logo是: 最专业的互动网络教学平台;
互动百科介绍:
YY教育 —— 最专业互动网络教学平台。 YY教育是一个聚集国内外知名教学机构和著名讲师的网络教育平台,致力于改变现有网络教学模式,提供更快捷、更方便、更有效的教学沟通服务。
乙:我也知道一些,比如
多贝公开课, 新浪微课堂,粉笔网 , 传课网(人家 logo 牛逼: 传播知识,改变命运!),几分钟网(浙大哥们办的),师徒网(开放式互联网学院),新浪公开课( 有栏目: TED 值得传播的创意 ),还有 沪江网校
甲:这些在线课程是好多...... 可我只想温习数据结构 ,有么?再请问, 这些网站的构建用到了哪些数据结构?
乙:你自个儿就站在金矿上呢...... 说起数据结构 ,可以看网易云课堂的视频: 麻省理工学院公开课 - 算法导论(http://study.163.com/plan/planIntroduction.htm?id=1200005#/planDetail)
甲:恩,算法和数据结构行影不离,谢谢。
乙:这样,给你一颗二叉树,用递归和非递归的办法求这棵树的层次,二叉树结点的数据结构是这样的:
typedef struct bitNode
{
ElemType data;
struct bitNode *lchild,*rchild;
} bitNode ;
甲:先说递归,有人这样回答,可行么?
//函数名称:
// template<class T>
// int GetHeight(TreeNode<T> *root)
//函数功能描述:
// 返回以root为根的树的树高
//函数调用之前的预备条件:
// 无
//返回后的处理:
// 无
//返回值(如果有的话):
// 树的高度
//函数的输入参数:
// TreeNode<T> *root顶点的指针
//函数的输出参数:
// 无
int GetHeight(TreeNode<T> *root)
{
if(root == NULL)
return 0;
return max(GetHeight(root->LeftMostChild) + 1, GetHeight(root->RightSibling));