第十章:树结构

10.1二叉树

10.1.1为什么需要树这种数据结构

1)数组存储方式的分析:
优点:通过下标方式访问元素,速度快。对于有序数组,还可使用二分查找提高检索速度。
缺点:如果要检索具体某个值,或者插入值(按一定顺序)会整体移动,效率较低
示意图:



2)链式存储方式的分析
优点:在一定程度上对数组存储方式有优化(比如:插入一个数值节点,只需要将插入节点,链接到链表中即可,删除效率也很好)。
缺点:在进行检索时,效率仍然较低,比如(检索某个值,需要从头节点开始遍历)
示意图:



3)树存储方式的分析
树存储能提高数据存储,读取的效率,比如利用二叉排序树(BinarySortTree),既可以保证数据的检索速度,同时也可以保证数据的插入,删除,修改的速度。
示意图:

树的常用术语(结合示意图理解):

1)节点
2)根节点
3)父节点
4)子节点
5)叶子节点(没有子节点的节点)
6)节点的权(节点值)
7)路径(从root节点找到该节点的路线)
8)层
9)子树
10)树的高度(最大层数)
11)森林:多颗子树构成森林

10.1.2二叉树的概念

1)树有很多种,每个节点最多只能有两个子节点的一种形式称为二叉树。
2)二叉树的子节点分为左节点和右节点
3)示意图:



4)如果该二叉树的所有叶子节点都在最后一层,并且结点总数=2^n-1,n为层数,则我们称为满二叉树。



5)如果该二叉树的所有叶子节点都在最后一层或者倒数第二层,而且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,我们称为完全二叉树

10.1.3二叉树遍历的说明

1)前序遍历:先输出父节点,再遍历左子树和右子树
2)中序遍历:先遍历左子树,再输出父节点,再遍历右子树
3)后序遍历:先遍历左子树,再遍历右子树,最后输出父节点

10.1.4二叉树遍历应用实例(前序,中序,后序)

应用实例的说明和思路:


10.1.5二叉树-查找指定节点

要求:
1)请编写前序查找,中序查找和后序查找的方法。
2)并分别使用三种查找方式,查找heroNO=5的节点
3)并分析各种查找方式,分别比较了多少次
4)示意图:


10.1.6二叉树-删除节点

要求(规定):
1)如果删除的节点是叶子节点,则删除该节点
2)如果删除的节点是非叶子节点,则删除该子树.
3)示意图:


10.1.5二叉树的遍历、查找、删除节点的所有代码:

class HeroNode():
    def __init__(self,id,name):
        self.id = id
        self.name = name
        self.left = None
        self.right = None
    def preOrder(self):
        #先输出父结点
        print(self.id,self.name)
        #递归向左子树前序遍历
        if self.left != None:
            self.left.preOrder()
        #递归向右子树前序遍历
        if self.right != None:
            self.right.preOrder()

    def infixOrder(self):
        if self.left != None:
            self.left.infixOrder()
        print(self.id,self.name)
        if self.right != None:
            self.right.infixOrder()

    def postOrder(self):
        if self.left != None:
            self.left.postOrder()   
        if self.right != None:
            self.right.postOrder()
        print(self.id,self.name)
             
    def preOrderSearched(self,id):
        # 1.先判断当前结点的no是否等于要查找的
        # 2.如果是相等,则返回当前结点    
        if self.id == id:
            return self
        print("compare",self.id)
        # 3.如果不等,则判断当前结点的左子节点是否为空,如果不为空,则递归前序查找,
        # 这里创建一个对象用来接收查找的返回值
        self.heronode = HeroNode(None,None)
        if self.left != None:
            print("left")
            self.heronode = self.left.preOrderSearched(id)
        # 4.如果左递归前序查找,找到结点,则返回这个对象,注意这里不能直接返回self,因为self是只当前节点,而不是self.heronode这个对象
        if self.heronode.id != None:
            return self.heronode
        # 5.否->继续判断,当前的结点的右子节点是否为空,如果不空,则继续向右递归前序查找.
        if self.right != None:
            print("right")
            self.heronode = self.right.preOrderSearched(id)
        # 6.不管向右递归前序查找有没有找到直接返回self.heronode对象即可。
        return self.heronode
    
    def infixOrderSearched(self,id):
        self.heronode = HeroNode(None,None)
        if self.left != None:
            print("left")
            self.heronode = self.left.infixOrderSearched(id)
        if self.heronode.id != None:
            return self.heronode
        if self.id == id:
            return self
        print("compare",self.id)
        if self.right != None:
            print("right")
            self.heronode = self.right.infixOrderSearched(id)
        return self.heronode 

    def postOrderSearched(self,id):
        self.heronode = HeroNode(None,None)
        if self.left != None:
            print("left")
            self.heronode = self.left.postOrderSearched(id)
        if self.heronode.id != None:
            return self.heronode
        if self.right != None:
            print("right")
            self.heronode = self.right.postOrderSearched(id)
        if self.heronode.id != None:
            return self.heronode
        if self.id == id:
            return self
        print("compare",self.id)
        return self.heronode

    def perdelete(self,id):
        #说明:
        #1.本删除方法,是按照前序查找的形式进行查找删除的
        #2.规定
        # //1.如果删除的节点是叶子节点,则删除该节点
        # //2.如果删除的节点是非叶子节点,则删除该子树
        #实现过程:
        #1.因为我们的二叉树是单向的,所以我们是判断当前结点的子结点是否需要删除结点,而不能去判断当前这个结点是不是需要删除结点.因此用self.left self.right
        #2.如果当前结点的左子结点不为空,并且左子结点就是要删除结点,就将this.left=null;并且就返回(结束递归删除)
        if self.left != None and self.left.id == id:
            self.left = None
            return
        #3.如果当前结点的右子结点不为空,并且右子结点就是要删除结点,就将this.right=null;并且就返回(结束递归删除)
        if self.right != None and self.right.id == id:
            self.right = None
            return
        #4.如果第2和第3步没有删除结点,那么我们就需要向左子树进行递归删除
        if self.left != None:
            self.left.perdelete(id)
        #5.如果第4步也没有删除结点,则应当向右子树进行递归删除.
        if self.right != None:
            self.right.perdelete(id)
        return


class BinaryTree():
    def __init__(self,id,name):
        self.id = id
        self.name = name
        self.headnode = HeroNode(self.id,self.name)

    def infixOrder(self):
        if self.headnode != None:
            self.headnode.infixOrder()
        else:
            print("None")
    
    def postOrder(self):
        if self.headnode != None:
            self.headnode.postOrder()
        else:
            print("None")

    def preOrder(self):
        if self.headnode != None:
            self.headnode.preOrder()
        else:
            print("None")

    def preOrderSearched(self,id):
        self.id = id
        if self.headnode != None:
            return self.headnode.preOrderSearched(id)
        else:
            return None
    
    def infixOrderSearched(self,id):
        self.id = id
        if self.headnode != None:
            return self.headnode.infixOrderSearched(id)
        else:
            return None
    
    def postOrderSearched(self,id):
        self.id = id
        if self.headnode != None:
            return self.headnode.postOrderSearched(id)
        else:
            return None
 
    def perdelete(self,id):
        #在这里先对root结点进行判断,若是则置空,不是再调用root结点的perdelete方法
        self.id = id
        if self.headnode != None and self.headnode.id == id:
            self.headnode = None
            return
        self.headnode.perdelete(self.id)

#这里手动创建二叉树并做出相应连接、后续会写代码按照一定规则的形式来创建二叉树
binary = BinaryTree(0,'q')
node1 = HeroNode(1,'w')
node2 = HeroNode(2,'e')
node3 = HeroNode(3,'r')
node4 = HeroNode(4,'t')
node5 = HeroNode(5,'y')
node6 = HeroNode(6,'u')
node7 = HeroNode(7,'I')

binary.headnode.left = node1
binary.headnode.right = node2
node2.left = node3
node2.right = node4
node3.left = node5
node3.right = node6
node4.right = node7

#前序中序后序遍历
binary.preOrder()
binary.infixOrder()
binary.postOrder()

#前序中序后序查找
# persearch = binary.preOrderSearched(6)
# if persearch != None:
#     print(persearch.id, persearch.name)
# print("--------------------------------")
# persearch = binary.infixOrderSearched(6)
# if persearch != None:
#     print(persearch.id, persearch.name)
# print("--------------------------------")
# persearch = binary.postOrderSearched(6)
# if persearch != None:
#     print(persearch.id, persearch.name)

#删除
binary.preOrder()
print("--------------------------------")
binary.perdelete(7)
binary.preOrder()

10.2顺序存储二叉树

10.2.1顺序存储二叉树的概念

从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换成树,树也可以转换成数组,示意图:


要求:
1)如二叉树的7个节点,要求以数组的方式来存放arr:[1,2,3,4,5,6,6]
2)在遍历数组arr时,仍然可以以前序遍历,中序遍历和后序遍历的方式完成结点的遍历
顺序存储二叉树的特点:
1)顺序二叉树通常只考虑完全二叉树
温习概念:
完全二叉树示意图

2)第n个元素的左子节点为2n+1
3)第n个元素的右子节点为2
n+2
4)第n个元素的父节点为(n-1)/2
5)n:表示二叉树中的第几个元素(从0开始编号如图所示)

10.2.2顺序存储二叉树遍历

需求:
给你一个数组{1,2,3,4,5,6,7},要求以二叉树前序遍历的方式进行遍历。前序遍历的结果应当为1,2,4,5,3,6,7

代码实现:

class ArrayBinaryTree():
   def __init__(self,array):
       self.array = array
       self.length = len(self.array)
   def perOrder(self,index):
       if self.length == 0:
           return
       print(self.array[index])
       if 2*index+1<self.length:
           self.perOrder(2*index+1)
       if 2*index+2<self.length:
           self.perOrder(2*index+2)

a = [1,2,3,4,5,6,7]
A = ArrayBinaryTree(a)
A.perOrder(0)

10.3线索化二叉树

10.3.1 问题提出:

将数列{1,3,6,8,10,14}构建成一颗二叉树,如图所示:


问题分析:

1)当我们对上面的二叉树进行中序遍历时,数列为{8,3,10,1,6,14}
2)但是6,8,10,14这几个节点的左右指针,并没有完全的利用上.
3)如果我们希望充分的利用各个节点的左右指针,让各个节点可以指向自己的前后节点,怎么办?
4)解决方案-线索二叉树

10.3.2线索二叉树基本介绍

1)n个结点的二叉链表中含有n+1【公式2n-(n-1)=n+1】个空指针域。利用二叉链表中的空指针域,存放指向该结点在某种遍历次序下的前驱和后继结点的指针(这种附加的指针称为"线索")
2)这种加上了线索的二叉链表称为线索链表,相应的二叉树称为线索二叉树(ThreadedBinaryTree)。根据线索性质的不同,线索二叉树可分为前序线索二叉树、中序线索二叉树和后序线索二叉树三种
3)一个结点的前一个结点,称为前驱结点
4)一个结点的后一个结点,称为后继结点

10.3.3线索二叉树应用案例

说明:将下面的二叉树,进行中序线索二叉树。中序遍历的数列为{8,3,10,1,14,6}



思路分析:中序遍历的结果:{8,3,10,1,14,6}



说明:
一、中序线索化二叉树如上图所示:

首先第一个叶子结点无前驱结点,最后一个叶子结点无后继结点,
其次如值为10的结点,则其前驱结点值为3,后继结点值为1,如图红线所示
二、当线索化二叉树后,Node节点的属性left和right,有如下情况:
1)left指向的是左子树,也可能是指向的前驱节点.
比如①节点left指向的左子树,而⑩节点的left指向的就是前驱节点.
2)right指向的是右子树,也可能是指向后继节点.
比如①节点right指向的是右子树,而⑩节点的right指向的是后继节点.

10.3.4遍历线索化二叉树

1)说明:对前面的中序线索化的二叉树,进行遍历
2)分析:因为线索化后,各个结点指向有变化,因此原来的遍历方式不能使用,这时需要使用新的方式遍历线索化二叉树,各个节点可以通过线型方式遍历,因此无需使用递归方式,这样也提高了遍历的效率。遍历的次序应当和中序遍历保持一致。

代码实现

class HeroNode():
    def __init__(self,id,name):
        self.id = id
        self.name = name
        self.left = None
        self.right = None
        self.lefttype = 0
        self.righttype = 0

class BinaryTree():
    def __init__(self):
        self.pre = HeroNode(None,None)
        self.pre.right = None 

    def threaded(self,node):
        #这一个程序还算好写的,但是有两个地方困扰了我一天,我已经差点要放弃了,已经在简书里用别人的代码,写着我遇到了xxx的问题,想找人帮忙解决
        #可是我写着写着的时候,突然想到,嗯?为什么会有这个错误?为什么(我在线索化最左边叶子结点的left结点的时候由于为空所以应该返回到最左边的叶子结点, 可以是我return后,叶子结点丢了,当前结点变为空了)
        #然后我就在想return空的原因,那不就是因为我self.node = node  我在self.threaded(node.left) 这里调用的时候,此时的node.left为None,当然你再
        #self.node = node,它也就为空了,那么解决办法就是不要这句代码。
        # self.node = node
        #node: 就是当前需要线索化的结点
        if node == None:
            return
        # 先线索化左子树
        self.threaded(node.left)
        # 线索化当前结点
        # 处理当前结点的前驱结点
        if node.left == None:
            node.left = self.pre
            node.lefttype = 1
         # 处理当前结点的后继结点
        if self.pre.id != None and self.pre.right == None:        
              self.pre.right = node
              self.pre.righttype = 1
        #第二个错误是下面这句代码。所以导致了我整个程序一直有bug,这个问题修复是看别人的代码,才修复好的,惭愧
        #node.pre = node
        self.pre = node
        # 线索化右子树
        self.threaded(node.right)
     # 中序遍历线索化二叉树
    def threaded_in_order(self, node):
        #用一个循环去判断,其实这里能获得的node== None: 的话只有两种情况。一种是node3.left 一种是node6.right, 这里很巧妙
        #第二个None用于找到结束位置也就是node6
        while node != None:    
            #这里用lefttype ==0: 找到第一个 lefttype ==1 的结点也就是3作为开始结点,并且这个可以找到每个小分支最左边结点这个很重要!要不然有的结点就漏了
            while node.lefttype ==0:
                node = node.left
            #其实从这里开始就是不断的输出当前结点,并 node = node.right  但是不能直接这么两句话写了,不然会造成死循环,因为当运行到最后一句代前
            #正常此时 的 node.righttype以及node.lefttype 都为0 因此加上最后一句代码,起了顺水推舟的作用,这样就跳开了上面的while循环
            print(node.id)
            while(node.righttype == 1):      
                node = node.right
                print(node.id)
            node = node.right

#这里手动创建二叉树并做出相应连接、后续会写代码按照一定规则的形式来创建二叉树
node0 = HeroNode(0,'q')
node1 = HeroNode(1,'w')
node2 = HeroNode(2,'e')
node3 = HeroNode(3,'r')
node4 = HeroNode(4,'t')
node5 = HeroNode(5,'y')
node6 = HeroNode(6,'u')
node7 = HeroNode(7,'I')
binary = BinaryTree()
node0.left = node1
node0.right = node2
node1.left = node3
node1.right = node4
node2.left = node5
node2.right = node6
binary.threaded(node0)
binary.threaded_in_order(node0)

10.4树结构的实际应用

11.1 堆排序

详见:
https://www.jianshu.com/p/ff61c524f5cf

11.2 赫夫曼树

11.2.1基本介绍

1)给定n个权值作为n个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(HuffmanTree),还有的书翻译为霍夫曼树。
2)赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近

11.2.2赫夫曼树几个重要概念和举例说明

1)路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1
2)结点的权及带权路径长度:若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积
3)树的带权路径长度:树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL(weightedpathlength),权值越大的结点离根结点越近的二叉树才是最优二叉树。
4)WPL最小的就是霍夫曼树


霍夫曼树

11.2.3霍夫曼树创建思路

首先,我们给定任一字符串如“Hello world,i love python”
然后会生成这样一些数据:
sourceData = [('H', 1), ('e', 2), ('l', 4), ('o', 4), (' ', 3), ('w', 1), ('r', 1), ('d', 1), (',', 1), ('i', 1), ('v', 1), ('p', 1), ('y', 1), ('t', 1), ('h', 1), ('n', 1)]
每一个数据项是一个元组,元组的第一项是数据内容,第二项是该数据的权重。也就是说,用于构建霍夫曼树的数据是带权重的。假设这些数据里面的字母a-f的权重是根据这些字母在一个文本出出现的概率计算得出的,字母出现的概率越高,则该字母的权重越大。例如字母 a 的权重为 8 .
拿到数据我们就可以来构建霍夫曼树了。
1)找出所有元素中权重最小的两个元素,即g(2)和c(3),
2)以g和c为子节点构建二叉树,则构建的二叉树的父节点的权重为 2+3 = 5.
3)从除g和c以外剩下的元素和新构建的权重为5的节点中选出权重最小的两个节点,
4)进行第 2 步操作。
以此类推,直至最后合成一个二叉树就是霍夫曼树。

11.2.4代码实现

代码参考:https://www.cnblogs.com/dongyangblog/p/11228930.html

class Node ():
    def __init__(self,data,value):
        self.value = value
        self.data = data
        self.left = None
        self.right = None

# 定义获取列表中权重最大的两个节点的方法:
#1.定义 result 列表 带有两个value为正无穷的 Node 对象
#2.将权重最小的两个结点放入 result 中
#3.将其他结点扔到list2中,包括从result淘汰的结点
def getmin2(list):
    result = [Node (None,float('inf')), Node (None,float('inf'))]
    list2 = []
    for i in range(len(list)):
        if list[i].value < result[0].value:
            if result[1].value != float('inf'):
                list2.append(result[1])
            result[0] , result[1] = list[i] , result[0]
        elif list[i].value < result[1].value:
            if result[1].value != float('inf'):
                list2.append(result[1])
            result[1] = list[i] 
        else:
            list2.append(list[i])
        # for i in range(len(result)):
        #     print("result",result[i].value)
        # for i in range(len(list2)):
        #     print("list2",list2[i].value)
    return result , list2

#定义生成哈夫曼树的方法:
#1.调用getmin2方法 获得 min2,分别为left、right结点,data 为剩下的结点
#2.创建一个father结点,并将left、right分别赋给 father.left father.right
#3.如果data里空了 说明没有剩余结点了 就可以返回 father了就是哈夫曼树
#4.如果data不是空的,那么就还得继续构造father结点, 并且记得把father结点扔到 data里面
#5.递归调用makeHuffman函数,也就继续调用getmin2函数,继续获得最小权重的两个结点
def makeHuffman(list):
    min2, data = getmin2(list)
    left = min2[0]
    right = min2[1]
    value = left.value + right.value
    father = Node(None, value)
    father.left = left
    father.right = right
    if data == []:
        return father
    data.append(father)
    return makeHuffman(data)

# 递归方式实现广度优先遍历
#1.先将Node对象的list转为列表,只是把类型改了,list 的属性都还在
#2.将值一个一个扔到result里面,先扔根结点,
# 3.然后判断当前跟结点有没有左右子结点,有的话将根结点的左子结点,右子结点分别扔到nextlist里去
#4.没有的话判断当前根结点是是其父结点的右子结点吗,若是则判断nextlist是否为空,
# 4.1 若为空说明以当前结点为根结点的树遍历完了(没有叶子结点),可以返回了
# 4.2 若不为空,说明还没有遍历完,调整下参数以便继续遍历
#5.若不是右子结点,则将index + 1 使当前指向右子结点继续遍历
#6 全遍历完,返回result
def traverse(list,index= 0 ,nextlist = [] ,result = []):
    if type(list)  == Node:
        list = [list]    
    result.append((list[index].data,list[index].value))
    if list[index].left != None:
        nextlist.append((list[index].left))
    if list[index].right != None:
        nextlist.append((list[index].right))
    if index == len(list)-1:
        if nextlist == []:
            return
        else:
            list = nextlist
            nextlist = []
            index = 0
    else:
        index +=1
    traverse(list,index,nextlist,result)
    return result
# 直接用前序遍历将其输出
# def traverse(list):
#     # if type(list)  == Node:
#     #     list = [list]  
#     print(list.data,list.value)
#     if list.left != None:
#         traverse(list.left)
#     if list.right != None:
#         traverse(list.right)



#文章中部分字母根据出现的概率规定权重,并让其生成Node对象
#将字符串转为携带自身字符及次数(权重)组成的元组的列表,再实例化Node对象
str = "Hello world,i love python"
#统计字符串出现字符的次数,并与字符组成字典
sourceData = {x:str.count(x) for x in str }
print("1",sourceData)
#sourceData.items() : 以列表形式返回可遍历的(键, 值) 元组数组。
#sourceData = sourceData.items() 也可以
sourceData = [(key,val) for key,val in sourceData.items()]
print("2",sourceData)
#将每个元组中的第0个元素与第一个元素作为参数实例化Node对象
sourceData = [Node(x[0], x[1]) for x in sourceData]
print("3",sourceData)
huffman = makeHuffman(sourceData)
# print(huffman.value)
# print(huffman.left.value)
# print(huffman.right.value)
# # print(huffman.left.left.value)
# # print(huffman.left.right.value)
# print(huffman.right.right.value)
# print(huffman.right.left.value)
huff = traverse(huffman)
print(huff)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容