链表

Warring: 本篇文章纯粹是为了勾引你去使用 stl 或 java 集合类,未必面面俱到,在文末我会推荐一些其他链接。

  大三以前我一直没写过什么大程序,一个程序顶多两三百行了事,总是不停地重造车轮:每个程序都重写一遍链表、栈、队列,认为这是依赖最少的“纯C程序”。

  后来《数据挖掘》第一次上机作业——挖频繁项集,我又开始写“纯C程序”了:一开始就轻松地实现了一个链表,然后我发现还得实现多个链表组成的集合,于是又得去实现一个“链表的链表”,这时我就觉得有点烦了:编程应该是一件快乐的事情,老是去折腾链表就无聊了,要是有直接能用的链表就好了。

  恰好C++的 stl 库和java的 util 包就提供了这样的链表: C++中的 list、java中 LinkedList。

使用它们至少有如下优点:

一 支持任意数据类型

  list 使用了模版,LinkedList 使用了泛型,使得它们支持各种数据类型:

// C++ 例子
#include <iostream>
#include <list>
using namespace std;

typedef struct _MyStruct{
    int a;
    double b;
}MyStruct;

int main()
{
    list<int> lint;
    list<MyStruct> lstruct;
    list<string> lclass;
    list<int*> lpoint;

    // 链表的链表
    list<list<int> > llist;
    /*上面有个空格是给VC6吃的,
    VS2010等都表示没胃口*/

    return 0;
}
// java 例子
import java.util.LinkedList;

interface MyInterface{
    public void nothing();
}

public class Temp {

    @SuppressWarnings("unused")
    public static void main(String[] args) {
        LinkedList<Integer> lint; // 基本类型使用包装类
        LinkedList<String> lclass;
        LinkedList<MyInterface> linter;// 接口也可以

        // 链表的链表
        LinkedList<LinkedList<Integer>> llist;
    }

}

二 定义后即可进行操作

  list 和 LinkedList 都是基于对象的,面向对象的一个特性就是数据和操作的整合,对象不仅有成员数据,还有成员函数,所以我们在定义了链表后就可以使用各种操作啦!VC、VS中C++对象引用成员函数可自动补齐,既省脑力又省指力,eclipse中java对象引用成员方法的自动补齐则更为犀利。

// C++ 例子
#include <iostream>
#include <list>
using namespace std;

int main()
{
    list<int> L;

    L.push_back(2);// 尾部追加

    L.push_back(3);
    L.push_front(1);// 头部添加

    L.pop_back();// 尾部删除
    L.pop_front();// 头部删除

    cout<<L.front()<<endl;
    // 输出结果是 2

    return 0;
}
// java 例子
import java.util.LinkedList;

public class Temp {

    public static void main(String[] args) {
        // java 的对象都是 new 出来的
        LinkedList<Integer> L = new LinkedList<Integer>();

        // 以下流程同 C++ 版
        L.addLast(2);

        L.add(3);// 同addLast
        L.addFirst(1);

        L.removeLast();
        L.removeFirst();

        System.out.println(L.getFirst());
    }

}

三 源码可见(授人以渔

list 和 LinkedList 等集合类是完全开源的,阅读源代码能解开一切疑惑。

C++

在 VC、VS 中选中记号,右键弹出菜单,选择“转到定义”:

然后就跳到了它定义的地方:

链表_第1张图片

  printf 等函数如果选择“转到定义”,我们还是只能看到它们在头文件中的声明,其具体实现是看不到的。但是 stl 的集合类的源代码全部写在头文件中,所以我们能看到完整的源代码。

  不过由于 stl 的实现使用了大量的宏,很难看明白,而我也不是靠 C++ 吃饭的,所以也就不自找麻烦,懒得去看了。所以如果你看到我说“list 是双向链表”,那是我从书上看到的,或者我猜的^_^。

java (eclipse中)

选中记号,一个框框自己就冒出来了:

链表_第2张图片

下面有两个按钮:

  •  是转到定义
  •  是转到在线文档,没有源代码,但是有丰富的使用方法 或 类关系树 等。

首次使用“转到定义”时可能会提示“Source not found”:

链表_第3张图片

点击 Attach Source 按钮,选择 jdk 安装目录下的 src.zip就可以了:
我的路径是D:/Program Files/Java/jdk1.7.0/src.zip

链表_第4张图片

我是怎么知道这些菜单/按钮的

  一开始刚使用 VC、eclipse 开发环境的时候我也什么都不懂,然后会写、编译、运行 Hello World 级的程序了,然后就试验性地使用一些平时不用的菜单/按钮,也许有些菜单/按钮可有可无,但是它们能提高效率,这也是很值得去掌握的。

四 可靠

  windows 和 linux 下 C++ 中都可以使用 stl,否则也不会被称为“标准模板库”了;而 java 的 util 包中的各种集合类也是跨平台使用的。

  我们自己写的链表有可能存在 Bug,但是使用 stl 和 util 的集合类就不用担心了:那是一群专业人士开发出来的,都用了N年了,要是程序中出现了 Bug,一定不是 list 或 LinkedList 的责任。

栈和队列

  查看源代码可以知道 list 和 LinkedList 都是双向链表, 两端都可以添加、删除元素,于是它们又是天生的栈和队列:

栈操作 list LinkedList
方案一 方案二 方案一 方案二
Push push_back push_front addLast addFirst
Pop 先back后pop_back 先front后pop_front removeLast removeFirst

队列

队列操作 list LinkedList
方案一 方案二 方案一 方案二
Enqueue push_back push_front addLast addFirst
Dequeue 先front后pop_front 先back后pop_back removeFirst removeLast

这些操作的时间复杂度都是 O(1),最优的O(∩_∩)O~。

 

这篇介绍了链表,顺带着把栈和队列也搞定了,我想你已经感觉到 stl 或 util 的强大了。C++ 设计得很复杂,还有操作符重载,所以我一直对 C++ 怀有成见,也正是发现了 stl 的强大,我才逐渐喜欢上 C++,现在如果做可执行程序的话我肯定选 C++,复杂的语言也可以简单地用不是!

推荐链接

三十分钟掌握STL(前半部分很不错,后半部分真心没看懂o(╯□╰)o)

你可能感兴趣的:(java,java,java,C++,C++,集合,STL,STL)