優(yōu)先隊(duì)列(PriorityQueue)

http://www.reibang.com/p/94155f9616bf

引入

在數(shù)據(jù)結(jié)構(gòu)中夸浅,普通的隊(duì)列是先進(jìn)先出,但有時(shí)我們可能并不想有這么固定的規(guī)矩扔役,我們希望能有一個(gè)帶優(yōu)先級(jí)的隊(duì)列帆喇。考慮在現(xiàn)實(shí)生活中亿胸,一些服務(wù)排隊(duì)窗口會(huì)寫著“軍人依法優(yōu)先”坯钦;送進(jìn)醫(yī)院的患者,即便是按順序到達(dá)的侈玄,生病更加嚴(yán)重的往往優(yōu)先級(jí)也會(huì)更高婉刀;還有操作系統(tǒng)中的作業(yè)調(diào)度也和優(yōu)先級(jí)有關(guān)......
于是我們能不能改進(jìn)隊(duì)列?使得隊(duì)列是有一定優(yōu)先級(jí)的序仙,這樣能讓一些事物和任務(wù)的處理變的更加靈活突颊。當(dāng)然是可以的,最基本的我們可以基于線性結(jié)構(gòu)來實(shí)現(xiàn)潘悼,考慮基于線性結(jié)構(gòu)的時(shí)間復(fù)雜度:

1律秃、隊(duì)列是一種FIFO(First-In-First-Out)先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),對(duì)應(yīng)于生活中的排隊(duì)的場(chǎng)景治唤,排在前面的人總是先通過棒动,依次進(jìn)行。
2宾添、優(yōu)先隊(duì)列是特殊的隊(duì)列船惨,從“優(yōu)先”一詞,可看出有“插隊(duì)現(xiàn)象”辞槐。比如在火車站排隊(duì)進(jìn)站時(shí)掷漱,就會(huì)有些比較急的人來插隊(duì),他們就在前面先通過驗(yàn)票榄檬。優(yōu)先隊(duì)列至少含有兩種操作的數(shù)據(jù)結(jié)構(gòu):insert(插入)卜范,即將元素插入到優(yōu)先隊(duì)列中(入隊(duì));以及deleteMin(刪除最小者)鹿榜,它的作用是找出海雪、刪除優(yōu)先隊(duì)列中的最小的元素(出隊(duì))。


image.png

結(jié)構(gòu)\操作 入隊(duì) 出隊(duì)
普通線性結(jié)構(gòu) O(1) O(n)
順序線性結(jié)構(gòu) O(n) O(1)
普通線性結(jié)構(gòu)實(shí)現(xiàn)的優(yōu)先隊(duì)列出隊(duì)時(shí)間復(fù)雜度是O(n)舱殿,因?yàn)槌鲫?duì)要拿出最優(yōu)先的元素奥裸,也就是相對(duì)最大的元素(注意:大小是相對(duì)的,我們可以指定比較規(guī)則)沪袭,從而要掃描一遍整個(gè)數(shù)組選出最大的取出才行湾宙。而對(duì)于順序線性結(jié)構(gòu)的入隊(duì)操作,入隊(duì)后可能破壞了原來的有序性,從而要調(diào)整當(dāng)前順序侠鳄。
可以看到使用線性結(jié)構(gòu)總有時(shí)間復(fù)雜度是O(n)的操作埠啃,還有沒有更好的實(shí)現(xiàn)方式呢,當(dāng)然是有的伟恶,這就要來聊一聊堆Heap碴开。

堆嚴(yán)格意義上來說又叫二叉堆(Binary Heap),因?yàn)樗慕Y(jié)構(gòu)是一顆完全二叉樹博秫,堆一般分為最大堆和最小堆潦牛。

堆性質(zhì):
結(jié)構(gòu)性:堆是一顆除底層外被完全填滿的二叉樹,底層的節(jié)點(diǎn)從左到右填入挡育,這樣的樹叫做完全二叉樹巴碗。即缺失結(jié)點(diǎn)的部分一定再樹的右下側(cè)。

堆序性:由于我們想很快找出最小元静盅,則最小元應(yīng)該在根上良价,任意節(jié)點(diǎn)都小于它的后裔寝殴,這就是小頂堆(Min-Heap)蒿叠;如果是查找最大元,則最大元應(yīng)該在根上蚣常,任意節(jié)點(diǎn)都要大于它的后裔市咽,這就是大頂堆(Max-heap)。

堆的分類

最大堆:父親節(jié)點(diǎn)的值大于孩子節(jié)點(diǎn)的值
最小堆:父親節(jié)點(diǎn)的值小于孩子節(jié)點(diǎn)的值

數(shù)組表示堆

由于是完全二叉樹抵蚊,節(jié)點(diǎn)的索引之間有著一定的關(guān)系施绎,故我們可以使用數(shù)組來存儲(chǔ)二叉堆,具體如下:


image.png

如果從索引為0開始存儲(chǔ)贞绳,則父親和孩子節(jié)點(diǎn)的索引關(guān)系如下:


image.png

堆的實(shí)現(xiàn)

上浮操作(shift up)

當(dāng)我們需要向一個(gè)最大堆添加一條新的數(shù)據(jù)時(shí)谷醉,此時(shí)我們的堆變成了這樣。


image.png

此時(shí)冈闭,由于新數(shù)據(jù)的加入已經(jīng)不符合最大堆的定義了俱尼。所以我們需要對(duì)新加入的數(shù)據(jù)進(jìn)行shift up操作,將它放到它應(yīng)該在的位置萎攒。shift up操作時(shí)我們將新加入的數(shù)據(jù)與它的父節(jié)點(diǎn)進(jìn)行比較遇八。如果比它的父節(jié)點(diǎn)大,則交換二者耍休。


image.png

并且不斷的重復(fù)這個(gè)操作刃永,將它與父節(jié)點(diǎn)比較,直到它不大于父節(jié)點(diǎn)羊精,或者它沒有父節(jié)點(diǎn)(到頂了)斯够。
image.png

此時(shí)我們就完成了 對(duì)新加入元素的shift up操作。

下沉操作(shift down)

當(dāng)我們從堆中(也就是優(yōu)先隊(duì)列中)取出一個(gè)元素時(shí)。我們是將堆頂?shù)脑貜棾觥?只能從堆頂取出)


image.png

此時(shí)這個(gè)堆沒有頂了读规,那么該怎么辦呢劫灶?我們只需要把這個(gè)堆最后一個(gè)元素放到堆頂就可以了。


image.png

image.png

此時(shí)這個(gè)堆已經(jīng)不符合最大堆的性質(zhì)掖桦。為了保持這個(gè)性質(zhì)本昏,我們需要將堆頂?shù)脑卣{(diào)整到它應(yīng)該在的位置。也就是對(duì)它進(jìn)行shift Down操作枪汪。在shift down時(shí)涌穆,因?yàn)樗凶笥液⒆觾蓚€(gè)節(jié)點(diǎn),所以我們需要將左右兩個(gè)孩子節(jié)點(diǎn)進(jìn)行比較雀久,在得到較大的節(jié)點(diǎn)之后宿稀,再與它進(jìn)行比較,如果它的子節(jié)點(diǎn)大赖捌,則將二者交換祝沸。并且不斷的重復(fù)這樣的操作,直到它沒有葉子節(jié)點(diǎn)或者大于葉子節(jié)點(diǎn)停止越庇。
image.png

image.png

此時(shí)我們就完成了彈出一個(gè)元素之后的shift down操作罩锐。

堆排序

replace

replace:去除最大元素后,放入一個(gè)新元素
實(shí)現(xiàn):可以先extractMax,再add卤唉,兩次longn操作涩惑。
實(shí)現(xiàn):將堆頂?shù)脑靥鎿Q以后sift down,一次O(logn)操作

heapify

將n個(gè)元素逐個(gè)插入到一個(gè)空堆中,算法復(fù)雜度是O(nlogn),heapify的過程桑驱,算法的復(fù)雜度為O(n).

heapify:將任意數(shù)組整理成堆的形狀竭恬。
首先將一個(gè)數(shù)組抽象成一個(gè)堆。這個(gè)過程熬的,我們稱之為heapify痊硕。


image.png

之后我們找到這個(gè)堆中第一個(gè)非葉子節(jié)點(diǎn),這個(gè)節(jié)點(diǎn)的位置始終是數(shù)組的數(shù)量除以2押框,也就是索引5位置的27岔绸,從這個(gè)節(jié)點(diǎn)開始,對(duì)每一個(gè)非葉子的節(jié)點(diǎn),强戴,進(jìn)行shift down操作亭螟。
27比它的子節(jié)點(diǎn)51要小,所以交換二者骑歹。


image.png

之后對(duì)索引4位置的11预烙,以及索引3位置的25,繼續(xù)進(jìn)行shift down道媚。
image.png

image.png

接下來我們看索引2位置的20扁掸。首先呢翘县,我們需要將20與它兩個(gè)子節(jié)點(diǎn)中較大的51交換。


image.png

此時(shí)谴分,還沒有完锈麸,shift down操作是直到它沒有葉子節(jié)點(diǎn)或者大于葉子節(jié)點(diǎn)時(shí)才停止。
所以我們需要繼續(xù)將20與它的子節(jié)點(diǎn)27進(jìn)行比較牺蹄。
image.png

索引2才算操作完成了忘伞。
最后繼續(xù)對(duì)索引1位置的14,以此類推進(jìn)行shiftdown沙兰。整個(gè)堆就操作完成氓奈。使用的時(shí)候每次取出堆頂?shù)脑兀麄€(gè)數(shù)組就是排序完成的了鼎天。
image.png

heapfiy 的復(fù)雜度

每個(gè)節(jié)點(diǎn)堆化的時(shí)間復(fù)雜度是O(logn)舀奶,那\frac{n}{2}+1個(gè)節(jié)點(diǎn)的堆化的總時(shí)間復(fù)雜度是O(nlogn)。
推導(dǎo)過程
堆化節(jié)點(diǎn)從倒數(shù)第二層開始斋射。堆化過程中育勺,需要比較和交換的節(jié)點(diǎn)個(gè)數(shù)與這個(gè)節(jié)點(diǎn)的高度k成正比。

image.png

將每個(gè)非葉子節(jié)點(diǎn)的高度求和罗岖,得到下面的公式S1:
image.png

這個(gè)公式的求解稍微有點(diǎn)技巧涧至,我們把公式左右都乘以2,得到另一個(gè)公式S2呀闻,再將S2減去S1化借,就可以得到S了潜慎。
image.png

S的中間部分是一個(gè)等比數(shù)列捡多,用等比數(shù)列的求和公式來計(jì)算,最終的結(jié)果就是下圖的樣子铐炫。
image.png

image.png

因?yàn)?img class="math-inline" src="https://math.jianshu.com/math?formula=h%3D%5Clog_2%20n" alt="h=\log_2 n" mathimg="1">垒手,代入公式S,就得到S=O(n)倒信,所以建堆的時(shí)間復(fù)雜度是O(n)科贬。

原地堆排序

所以 heapify() 時(shí)間復(fù)雜度是 O(n).
建堆后,數(shù)組中的數(shù)據(jù)是大頂堆鳖悠。把堆頂元素榜掌,即最大元素,跟最后一個(gè)元素交換乘综,那最大元素就放到了下標(biāo)為n的位置憎账。
這個(gè)過程有點(diǎn)類似上面的“刪除堆頂元素”的操作,當(dāng)堆頂元素移除之后卡辰,把下標(biāo)n的元素放堆頂胞皱,然后再通過堆化的方法邪意,將剩下的n-1個(gè)元素重新構(gòu)建成堆。一直重復(fù)這個(gè)過程反砌,直到最后堆中只剩下下標(biāo)為1的元素雾鬼,排序就完成了。


image.png
// n表示數(shù)據(jù)的個(gè)數(shù)宴树,數(shù)組a中的數(shù)據(jù)從下標(biāo)1到n的位置策菜。


public class HeapSort {

    public HeapSort() {
    }

    public static <E extends Comparable<E>> void sort(E[] data) {
        MaxHeap<E> maxHeap = new MaxHeap();
        for (E datum : data) {
            maxHeap.add(datum);
        }
        for (int i = data.length - 1; i >= 0; i--) {
            data[i] = maxHeap.extractMax();
        }
    }

    //原地堆排序
    public static <E extends Comparable<E>> void sort2(E[] data) {
        if (data.length == 1) return;
        //將數(shù)組整理成堆
        //(data.length-2)/2:最后一個(gè)非葉子結(jié)點(diǎn)
        //轉(zhuǎn)換成堆
        for (int i = (data.length - 2) / 2; i >= 0; i--) {
            siftDown(data, i, data.length);
        }
        //進(jìn)行堆排序
        for (int i = data.length - 1; i >= 0; i--) {
            swap(data, 0, i);
            siftDown(data, 0, i);
        }
    }

    //下沉操作
    //對(duì)data[0,n)所形成的最大堆中,索引k的元素酒贬,執(zhí)行siftdown
    private static <E extends Comparable<E>> void siftDown(E[] data, int k, int n) {
        //結(jié)點(diǎn)k的左孩子已經(jīng)越界了,循環(huán)結(jié)束
        while (2 * k + 1 < n) {
            //左孩子的結(jié)點(diǎn)
            int j = 2 * k + 1;
            //右孩子的結(jié)點(diǎn),判斷有孩子是否存在做入,并且有孩子的值是否大于左孩子。
            if (j + 1 < n && data[j + 1].compareTo(data[j]) > 0) {
                j++;
            }
            //當(dāng)前值比孩子的值小
            if (data[k].compareTo(data[j]) > 0) {
                break;
            }
            //交換
            swap(data, k, j);
            k = j;
        }
    }

    private static <E extends Comparable<E>> void swap(E[] data, int i, int j) {
        E ele = data[i];
        data[i] = data[j];
        data[j] = ele;
    }

    public static void main(String[] args) {
        Integer[] arr = {1, 65, 98, 65, 5, 65, 12};
        sort2(arr);
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

代碼

package com.libin.setandmap;

import java.util.Random;

public class MaxHeap<E extends Comparable<E>> {
    private Array<E> data;

    public MaxHeap() {
        this.data = new Array<>();
    }

    public int size() {
        return data.getSize();
    }

    //返回一個(gè)布爾值同衣,表示堆中是否為空
    public boolean isEmpty() {
        return data.isEmpty();
    }

    //返回完全二叉樹數(shù)組表示中,一個(gè)索引表示的元素的父親結(jié)點(diǎn)的索引竟块。
    private int parent(int index) {
        if (index == 0) {
            throw new IllegalArgumentException("index-0 doesn't dont have parent");
        }
        return (index - 1) / 2;
    }

    //返回完全二叉樹數(shù)組表示中,一個(gè)索引表示的元素的左孩子結(jié)點(diǎn)的索引。
    private int leftChild(int index) {
        return index * 2 + 1;
    }

    //返回完全二叉樹數(shù)組表示中,一個(gè)索引表示的元素的右孩子結(jié)點(diǎn)的索引耐齐。
    private int rightChild(int index) {
        return index * 2 + 2;
    }

    public void add(E e) {
        data.addLast(e);
        //上浮的元素
        siftUp(data.getSize() - 1);
    }

    private void siftUp(int k) {
        while (k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0) {
            //與父節(jié)點(diǎn)進(jìn)行交換
            data.swap(k, parent(k));
            k = parent(k);
        }
    }

    public E findMax() {
        if (data.getSize() == 0) {
            throw new IllegalArgumentException("empty");
        }
        return data.get(0);
    }

    public E extractMax() {
        E max = findMax();
        data.swap(0, data.getSize() - 1);
        data.removeLast();
        siftDown(0);
        return max;
    }

    //下沉操作
    private void siftDown(int k) {
        //結(jié)點(diǎn)k的左孩子已經(jīng)越界了,循環(huán)結(jié)束
        while (leftChild(k) < data.getSize()) {
            //左孩子的結(jié)點(diǎn)
            int j = leftChild(k);
            //右孩子的結(jié)點(diǎn),判斷有孩子是否存在浪秘,并且有孩子的值是否大于左孩子。
            if (j + 1 < data.getSize() && data.get(j + 1).compareTo(data.get(j)) > 0) {
                j++;
            }
            //當(dāng)前值比孩子的值小
            if (data.get(k).compareTo(data.get(j)) > 0) {
                break;
            }
            //交換
            data.swap(k, j);
            k = j;
        }
    }

    //去除最大元素,然后添加一個(gè)元素埠况。
    public E replace(E e) {
        E ret = findMax();
        data.set(0, e);
        siftDown(0);
        return ret;
    }


    //heapfiy
    public MaxHeap(E[] arr) {
        data = new Array<>(arr);
        //去除最后一個(gè)元素的父元素耸携。
        for (int i = parent(arr.length - 1); i >= 0; i--) {
            siftDown(i);
        }
    }


    public static void main(String[] args) {
        int n = 100;
        Integer[] arr = new Integer[n];
        Random random = new Random();
        for (int i = 0; i < n; i++) {
            arr[i] =random.nextInt(Integer.MAX_VALUE);
        }
        MaxHeap<Integer> maxHeap = new MaxHeap<>(arr);
        for (int i = 0; i < n; i++) {
            System.out.println(maxHeap.extractMax());
        }
        System.out.println("finisehd");
    }

}

package com.libin.setandmap;


import java.util.Arrays;

public class Array<E> {
    private E[] data;
    private int size;

    //構(gòu)造函數(shù),傳入數(shù)組的容量capacity的Array
    @SuppressWarnings("unchecked")
    public Array(int capacity){
        data = (E[]) new Object[capacity];
        size = 0;
    }

    //午參構(gòu)造函數(shù)辕翰,默認(rèn)capacity為10
    public Array(){
        this(10);
    }

    public Array(E[] arr){
        data  = (E[]) new Object[arr.length];
        for (int i = 0; i <arr.length ; i++) {
            data[i] = arr[i];
        }
        size = arr.length;
    }
    //獲取數(shù)組中元素個(gè)數(shù)
    public int getSize(){
        return size;
    }

    //獲取數(shù)組的容量
    public int getCapacity(){
        return data.length;
    }

    //判斷數(shù)組是否為空
    public boolean isEmpty(){
        return size == 0;
    }

    //在數(shù)組下標(biāo)為index的位置插入一個(gè)元素
    public void add(int index , E e){

        if(index<0||index>size){
            throw new IllegalArgumentException("add failed , required index > 0 and index < size");
        }
        if(size == data.length){
            resize(data.length * 2);
        }
        for(int i=size-1;i>index;i--){
            data[i+1] = data[i];
        }
        data[index] = e;
        size++;
    }

    //向所有元素后添加一個(gè)新元素
    public void addLast(E e){
        add(size , e);
    }

    //向所有元素前添加一個(gè)新元素
    public void addFirst(E e){
        add(0 , e);
    }

    //獲取index索引位置的元素
    public E get(int index){
        if(index<0||index>=size){
            throw new IllegalArgumentException("get failed , required index > 0 and index < size");
        }

        return data[index];
    }

    //修改索引index位置的元素為e
    public void set(int index, E e){
        if(index<0||index>=size){
            throw new IllegalArgumentException("set failed , required index > 0 and index < size");
        }

        data[index] = e;
    }

    //判斷數(shù)組中是否含有元素e
    public boolean contains(E e){
        for(int i = 0;i<size;i++){
            if(e.equals(data[i])){
                return true;
            }
        }
        return false;
    }

    //查找數(shù)組中是否含有元素e夺衍,返回相應(yīng)元素的下標(biāo)
    public int find(E e){
        for(int i = 0;i<size;i++){
            if(e.equals(data[i])){
                return i;
            }
        }
        return -1;
    }

    //從數(shù)組中刪掉相應(yīng)下標(biāo)的元素,返回刪掉的元素
    public E remove(int index){
        if(index<0||index>=size){
            throw new IllegalArgumentException("remove failed , required index > 0 and index < size");
        }

        E ret = data[index];
        for(int i=index+1;i<size;i++){
            data[i-1] = data[i];
        }
        size--;
        data[size] = null;

        if(size == data.length/4 && data.length/2 != 0){
            resize(data.length/2);
        }
        return ret;
    }

    //從數(shù)組中刪掉第一個(gè)元素喜命,返回刪掉的元素
    public E removeFirst(){
        return remove(0);
    }

    //從數(shù)組中刪掉最后一個(gè)元素沟沙,返回刪掉的元素
    public E removeLast(){
        return remove(size-1);
    }

    //從數(shù)組中刪掉元素e
    public void removeElement(E e){
        int index = find(e);

        if(index != -1){
            remove(index);
        }
    }

    public void swap(int i,int j){
        E t = data[i];
        data[i] = data[j];
        data[j] =t;
    }

    @Override
    public String toString() {
        return "Array [data=" + Arrays.toString(data) + ", size=" + size +" Capacity="+data.length+ "]";
    }

    //重新設(shè)置數(shù)組容量
    private void resize(int newCapacity){
        @SuppressWarnings("unchecked")

        E[] newData = (E[]) new Object[newCapacity];
        for(int i=0;i<size; i++){
            newData[i] = data[i];
        }
        data = newData;
    }
}


優(yōu)先隊(duì)列

package com.libin.setandmap.heap;

public class PriorityQueue<E extends Comparable<E>>{

    private MaxHeap<E> maxHeap;

    public PriorityQueue() {
        this.maxHeap = new MaxHeap();
    }

    public int getSize(){
        return maxHeap.size();
    }

    public boolean isEmpty(){
        return maxHeap.isEmpty();
    }

    public E getFront(){
        return maxHeap.findMax();
    }

    public void enqueue(E e){
        maxHeap.add(e);
    }

    public E deQueue(){
        return maxHeap.extractMax();
    }
}

快排思想和優(yōu)先隊(duì)列比較

topk和selectk問題既可以使用快排思想解決,也可以使用優(yōu)先隊(duì)列解決壁榕。
快排:O(n) 空間O(1)
優(yōu)先隊(duì)列:O(nlogk) 空間O(k)
優(yōu)先隊(duì)列的有i是矛紫,不需要一次性知道所有數(shù)據(jù),數(shù)據(jù)流的方式處理。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末牌里,一起剝皮案震驚了整個(gè)濱河市颊咬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌牡辽,老刑警劉巖喳篇,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異态辛,居然都是意外死亡麸澜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門因妙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來痰憎,“玉大人票髓,你說我怎么就攤上這事∠吃牛” “怎么了洽沟?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)蜗细。 經(jīng)常有香客問我裆操,道長(zhǎng),這世上最難降的妖魔是什么炉媒? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任踪区,我火速辦了婚禮,結(jié)果婚禮上吊骤,老公的妹妹穿的比我還像新娘缎岗。我一直安慰自己,他們只是感情好白粉,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布传泊。 她就那樣靜靜地躺著,像睡著了一般鸭巴。 火紅的嫁衣襯著肌膚如雪眷细。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天鹃祖,我揣著相機(jī)與錄音溪椎,去河邊找鬼。 笑死恬口,一個(gè)胖子當(dāng)著我的面吹牛校读,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播楷兽,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼地熄,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了芯杀?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤雅潭,失蹤者是張志新(化名)和其女友劉穎揭厚,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扶供,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筛圆,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椿浓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片太援。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡闽晦,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出提岔,到底是詐尸還是另有隱情仙蛉,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布碱蒙,位于F島的核電站荠瘪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏赛惩。R本人自食惡果不足惜哀墓,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望喷兼。 院中可真熱鬧篮绰,春花似錦、人聲如沸季惯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽星瘾。三九已至走孽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間琳状,已是汗流浹背磕瓷。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留念逞,地道東北人困食。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像翎承,于是被迫代替她去往敵國(guó)和親硕盹。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容