范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

长文警告!红黑树详解!

  红黑树
  首先红黑树是一种平衡树,通过红黑染色的方式保持平衡 术语解释NIL :NIL节点是一个空节点,我们可以认为它是一个空指针指向的节点,代表这里什么也没有,在红黑树中我们认为一个NIL节点的颜色默认为黑色,虽然并没有一个实际的节点储存这个颜色信息红黑树必须满足以下四条性质:Every node is either red or black. All NIL nodes (figure 1) are considered black. A red node does not have a red child. Every path from a given node to any of its descendant NIL nodes goes through the same number of black nodes.
  由以上四个限制可以得到以下性质:
  the path from the root to the farthest leaf is no more than twice as long as the path from the root to the nearest leaf
  这个结果很容易想到,根节点到达每个叶节点上的黑色节点数一样,那么最长路径和最短路径之间的节点数量差别只有红色节点,而红色节点不能连续出现(由限制3)可知),所以最长路径最多是最短路径的两倍(红黑交替和全黑)
  这就使得红黑树能够维持一个高平衡性,保证了最长路径和最短路径的差值不会太大Linux中的红黑树的使用
  在具体学习红黑树的代码之前,我们先看一下Linux源码中对红黑树使用的文档和代码: searchstruct mytype *my_search(struct rb_root *root, char *string) {       struct rb_node *node = root->rb_node;        while (node) {               struct mytype *data = container_of(node, struct mytype, node);               int result;                result = strcmp(string, data->keystring);                if (result < 0)                       node = node->rb_left;               else if (result > 0)                       node = node->rb_right;               else                       return data;       }       return NULL; }
  其中用到的数据结构定义如下: struct rb_root { 	struct rb_node *rb_node; };  struct rb_node { 	unsigned long  __rb_parent_color; 	struct rb_node *rb_right; 	struct rb_node *rb_left; };  struct mytype {       struct rb_node node;       char *keystring; };
  然后我们看一下  container_of   的定义:#define container_of(ptr, type, member)                        ({                                                             const typeof(((type*)0)->member)* __mptr = (ptr);          (type*)((char*)__mptr - offsetof(type, member));       })
  宏的作用是:
  接收指向一个对象(数据)的指针,这个数据所属于的结构体的类型,以及这个数据在结构体中的成员名,返回指向这个结构体的指针
  简而言之就是取容器
  所以  container_of(node, struct mytype, node)  这个宏的作用就是从 node  这个属于红黑树部分的结构体,获得它的容器,从而得到具体的数据
  这里 container_of()  的原理是通过计算指定成员的偏移量,以及其地址,计算出包含它的结构的地址
  这里采用了类似装饰器的想法, mytype  把红黑树节点包起来,使得数据可以和红黑树分开单独编写逻辑,这是在没有类和模板之类的东西的C语言下对代码复用的一种实现
  知道这一部分的设计思想后,搜索部分就是简单的BST的搜索过程,由于储存的是字符串,所以使用  strcmp()  来比较数据的大小insert
  下面是插入操作的代码: int my_insert(struct rb_root *root, struct mytype *data) {       struct rb_node **new = &(root->rb_node), *parent = NULL;        /* Figure out where to put new node */       while (*new) {               struct mytype *this = container_of(*new, struct mytype, node);               int result = strcmp(data->keystring, this->keystring);                parent = *new;               if (result < 0)                       new = &((*new)->rb_left);               else if (result > 0)                       new = &((*new)->rb_right);               else                       return FALSE;       }        /* Add new node and rebalance tree. */       rb_link_node(&data->node, parent, new);       rb_insert_color(&data->node, root);        return TRUE; }
  在寻找插入节点部分和一般的BST一样,找到插入位置后使用  rb_link_node()  将节点插入到红黑树中,然后使用 rb_insert_color()  来维护红黑树的性质(之前提到的四条规则)
  关于如何维护红黑树的性质及其具体代码,我们在后面的实现中再讨论removing and replacing
  删除操作和替换操作是Linux中自带实现的,只需要调用函数即可: void rb_erase(struct rb_node *victim, struct rb_root *tree); void rb_replace_node(struct rb_node *old, struct rb_node *new,                       struct rb_root *tree);
  只要找到了指定的节点,就可以通过这两个函数来删除或者替换节点 次序相关的操作struct rb_node *rb_first(struct rb_root *tree); struct rb_node *rb_last(struct rb_root *tree); struct rb_node *rb_next(struct rb_node *node); struct rb_node *rb_prev(struct rb_node *node);
  这四个函数可以在任意一棵红黑树中找到最小值、最大值、后继、前驱
  相关的操作在BST中都会介绍到 红黑树的操作
  现在知道了红黑树的限制,我们的工作就是如何让BST的操作能够满足上面的四个性质,下面我们一个个操作来说:
  (这里采用的是wikipedia的代码,linux的代码我们最后再看)
  首先请记住上图第一张中的N、P、S、C、D节点的位置,本文来自我的学习笔记,所以并没有很多配图,红黑树的核心操作就来源于这五个节点的变化,请对号入座插入
  首先关于红黑树所使用的结构如下: enum color_t { BLACK, RED };  struct RBnode {     // node of red–black tree   RBnode* parent;   // == NIL if root of the tree   RBnode* child[2]; // == NIL if child is empty     // The index is:     //   LEFT  := 0, if (key < parent->key)     //   RIGHT := 1, if (key > parent->key)   enum color_t color;   int key; };  #define NIL   NULL // null pointer  or  pointer to sentinel node #define LEFT  0 #define RIGHT 1 #define left  child[LEFT] #define right child[RIGHT]  struct RBtree { // red–black tree   RBnode* root; // == NIL if tree is empty };
  首先我们要插入一个新的节点,通过一般BST的方式找到该节点对应的位置: RBnode** find_place(RBtree* tree, int key) {         RBnode** node = &tree->root;         while (*node != nullptr) {                 if (key < (*node)->key)                         node = &(*node)->left;                 else if (key > (*node)->key)                         node = &(*node)->right;                 else                         return nullptr;         } }
  这里和Linux源码一样使用了指针的指针,用来得到结构  RBnode  的中指针 left  和 right  ,这样能够方便直接修改一个节点的父节点
  找到这个节点的位置后我么可以直接将其插入红黑树,为了维持红黑树的第四性质:
  Every path from a given node to any of its descendant NIL nodes goes through the same number of black nodes.
  我们默认插入的节点为红色,并且检测当前的节点的case
  这里的case指的是一个节点附近和它相连的一系列节点的构成情况,是否构成一个违反红黑树性质的情况
  我们把插入后的情况检查分为6种: case 1
  插入的节点的父节点是黑色,此时红黑树性质不被破坏,不做任何改动 case 2
  如果P节点和U节点都是红色,那么祖父节点一定是黑色,为了维护红黑树,我们需要把P和U节点染成黑色,然后把G节点染成红色,这样局部满足了红黑树性质
  同时,为了让祖父节点不破坏 role3 ,我们把N节点设置为G,然后循环这个过程,直到N节点为空,或者构成不需要修改的情况case 3
  如果插入的节点为根节点,则不需要改动 case 4
  如果插入的父节点是红色且为根节点,则改变父节点的颜色为黑色即可
  上述四种情况都很简单,代码如下: void RBinsert1(RBtree* T,         // -> red–black tree                struct RBnode* N,  // -> node to be inserted                struct RBnode* P,  // -> parent node of N ( may be NULL )                byte dir)  // side ( LEFT or RIGHT ) of P where to insert N {     struct RBnode* G;  // -> parent node of P     struct RBnode* U;  // -> uncle of N      N->color = RED;     N->left = NIL;     N->right = NIL;     N->parent = P;     if (P == NULL) {  // There is no parent         T->root = N;  // N is the new root of the tree T.         return;       // insertion complete     }     P->child[dir] = N;  // insert N as dir-child of P     // start of the (do while)-loop:     do {         if (P->color == BLACK) {             // Case_I1 (P black):             return;  // insertion complete         }         // From now on P is red.         if ((G = P->parent) == NULL)             goto Case_I4;  // P red and root         // else: P red and G!=NULL.         dir = childDir(P);  // the side of parent G on which node P is located         U = G->child[1 - dir];              // uncle         if (U == NIL || U->color == BLACK)  // considered black             goto Case_I56;                  // P red && U black                                             // Case_I2 (P+U red):         P->color = BLACK;         U->color = BLACK;         G->color = RED;         N = G;  // new current node                 // iterate 1 black level higher                 //   (= 2 tree levels)     } while ((P = N->parent) != NULL);     // end of the (do while)-loop
  wikipedia的代码和Linux源码实现的代码架构不太一样
  这里的代码将数据包含在节点类中,我们通过迭代找到需要插入位置的父节点,然后通过  dir  来确定插入的方向,然后直接将 N  接到 P  的后面
  同时设置 N  的默认颜色为红色等case 5 and 6
  接下来我们进入case 5和6,首先我们已经确定P节点为红色,然后U节点为黑色,这样我们就不能通过染色解决问题,这样不能两边同时改变 黑色节点数量 (我们接下来称为Black height)
  红黑树选择的解决方式如下: 首先我们需要保证  N  节点和P  节点都在同一方向,也就是说,如果N  节点是 P  节点的左子节点,那么 P  节点就是 G  节点的左子节点;如果 N  节点是 P  节点的右子节点,那么 P  节点就是 G  节点的右子节点
  如果不能满足以上要求的话,进入case 5: 将  P  节点按照自己所在的方向旋转,即,如果 P  节点是左子节点, N  节点是右子节点,那么将 P  节点进行左旋,然后将旋转后的 P  节点设置为新的 N  节点
  这样我们就构建出了一个case 6:
  此时我们发现一个问题,旋转操作是会改变RBtree的Black Height的,简单列举几种情况即可发现这个问题
  但是这里旋转的两个节点都是红色节点,所以对于Black Height并没有影响,但是对于case 6而言,我们就需要对黑色节点进行旋转了 我们将  G  节点按照 P  节点所在方向的反方向旋转,使得 P  节点代替原本 G  节点的位置,此时右子树的Black height增加1,左子树的Black Height减少1,为了维护role 4,我们将 G  节点染为红色,P  节点染为黑色,此时我们发现,role 3和role 4同时满足了
  这么一来,插入的6种case就考虑完毕了,下面是case 5、6的代码部分: if (N == P->child[1 - dir]) {  // Case_I5 (P red && U black && N inner                                // grandchild of G):     RotateDir(P, dir);         // P is never the root     N = P;                     // new current node     P = G->child[dir];         // new parent of N                                // fall through to Case_I6 } // Case_I6 (P red && U black && N outer grandchild of G): RotateDirRoot(T, G, 1 - dir);  // G may be the root P->color = BLACK; G->color = RED; return;  // insertion complete          // end of RBinsert1 删除
  删除操作的简单情况: 删除节点为根节点,直接删除即可 一个节点如果只有一个非NIL子节点,那么这个子节点一定是红色,如果是黑色,那么Role 4一定会被破坏,黑色子节点至少多贡献一个Black Height 这样的话,如果 N  是红色节点,那么它就不能只拥有一个节点,而是要么没有子节点,要么有两个黑色子节点如果  N  是黑色节点,那么它可以拥有一个红色子节点,或者没有子节点,或者两个黑色子节点
  对于一个只有一个子节点的红色节点,由于一定没有子节点,所以我们可以直接删除这个节点
  对于只有一个子节点的黑色节点,其子节点一定是红色,我们可以将其直接替换删除节点,然后将其染为黑色,从而满足Role 4
  考虑了只有一个子节点和根节点的简单情况后,我们来考虑有两个子节点的情况: 如果一个节点同时拥有左右节点的话,我们可以寻找其前驱或者后继进行替换,然后将后继节点作为对象删除即可
  前驱或后继节点一定是只有一个子节点,或者本身就是叶子节点,所以至此我们只剩下最后一种情况:
  如果一个黑色节点没有子节点,我们将其删除后必然会破坏Role 4,此时需要进行删除后的红黑树维护 删除后的维护
  删除后操作我们总共要关注5个节点的情况:
  S  、 N  、P  、C  和 D  节点case 1
  如果删除的黑色节点是一个新的根节点,那么直接删除即可 Case_D1 (P == NULL):         return; // deletion complete case 2
  C  和 D  节点我们认为是 S  节点的子节点
  S  节点是 N  节点的兄弟节点,当 S  节点和 P  节点都是黑色,且C  和 D  节点也是黑色时,采取以下操作:我们将  S  节点染为红色,但是这样会使得经过S节点的路径Black Height减少,局部维护的同时破坏了整体的Role 4,所以我们把 P  节点当做新的 N  节点,继续进行删除后的维护void RBdelete2(   RBtree* T,         // -> red–black tree   struct RBnode* N)  // -> node to be deleted  {   struct RBnode* P = N->parent;  // -> parent node of N   byte dir;          // side of P on which N is located (∈ { LEFT, RIGHT })   struct RBnode* S;  // -> sibling of N   struct RBnode* C;  // -> close   nephew   struct RBnode* D;  // -> distant nephew    // P != NULL, since N is not the root.   dir = childDir(N); // side of parent P on which the node N is located   // Replace N at its parent P by NIL:   P->child[dir] = NIL;   goto Start_D;      // jump into the loop    // start of the (do while)-loop:   do {     dir = childDir(N);   // side of parent P on which node N is located Start_D:     S = P->child[1-dir]; // sibling of N (has black height >= 1)     D = S->child[1-dir]; // distant nephew     C = S->child[  dir]; // close   nephew     if (S->color == RED)       goto Case_D3;                  // S red ===> P+C+D black     // S is black:     if (D != NIL && D->color == RED) // not considered black       goto Case_D6;                  // D red && S black     if (C != NIL && C->color == RED) // not considered black       goto Case_D5;                  // C red && S+D black     // Here both nephews are == NIL (first iteration) or black (later).     if (P->color == RED)       goto Case_D4;                  // P red && C+S+D black     // Case_D2 (P+C+S+D black):     S->color = RED;     N = P; // new current node (maybe the root)     // iterate 1 black level     //   (= 1 tree level) higher   } while ((P = N->parent) != NULL);   // end of the (do while)-loop
  来自Wikipedia的伪代码,有着详细的注释 case 3
  若  S  节点是红色节点,C  和 D  是黑色节点,进行以下操作:将  P  节点按 N  节点的方向旋转,然后将 P  节点染为红色,将 S  节点染为黑色,此时的 S  节点就变为了原来的 C  节点(一定是黑色节点)Case_D3: // S red && P+C+D black:   RotateDirRoot(T,P,dir); // P may be the root   P->color = RED;   S->color = BLACK;   S = C; // != NIL   // now: P red && S black   D = S->child[1-dir]; // distant nephew   if (D != NIL && D->color == RED)     goto Case_D6;      // D red && S black   C = S->child[  dir]; // close   nephew   if (C != NIL && C->color == RED)     goto Case_D5;      // C red && S+D black   // Otherwise C+D considered black.   // fall through to Case_D4
  这样一来,我们要考虑的case就变成了: N  黑,P  红,S  黑
  接下来我们要考虑的case就是 C  和 D  节点的不同情况:case 4
  如果  D  和 C  都是黑色,那么将 S  染为红色,将 P  染为黑色,这样相当于给右子树的Black height加一,直接完成了红黑树的维护Case_D4: // P red && S+C+D black:   S->color = RED;   P->color = BLACK;   return; // deletion complete case 5
  我们认为  C  节点是左子节点,D  节点是右子节点
  如果 C  节点为红色,不管 P  节点是黑还是红,我们都可以直接执行下面的操作:将  S  节点和 C  节点进行旋转,然后交换两者的颜色Case_D5: // C red && S+D black:   RotateDir(S,1-dir); // S is never the root   S->color = RED;   C->color = BLACK;   D = S;   S = C;   // now: D red && S black   // fall through to Case_D6
  这么一来,红色就从  C  节点转移到了 D  节点的位置上,于是我们进入了最后的case 6case 6
  此时的  D  节点是红色,不管 P  节点是黑还是红,我们都可以直接执行下面的操作:将  P  和 S  节点旋转,然后交换两者的颜色,并把 D  节点染为黑色Case_D6: // D red && S black:   RotateDirRoot(T,P,dir); // P may be the root   S->color = P->color;   P->color = BLACK;   D->color = BLACK;   return; // deletion complete } // end of RBdelete2
  到此为止,基本的红黑树过程已经阐述完毕,我们下面总结一下红黑树的这些操作到底在干什么,问什么要这样干 旋转
  首先要提及的就是旋转操作,旋转操作我们可以看作一个子节点(N)和一个父节点(P)交换位置
  对于图中的三个框起来的子树部分,旋转操作的影响如下: N  子树上的路径全部会多经过一个S  点D  子树上的路径全部会少经过一个 P  点C  子树上的路径不会有任何改变
  结合起  P  和 S  这两个旋转对象的颜色,旋转操作可以在不改变BST性质的情况下改变 N  子树和 D  子树Black height,这是旋转操作在红黑树维护中扮演的角色
  但是旋转会改变Black height,也有可能将红色的  C  节点接到红色的 P  节点上,所以一般旋转后还需要重新进行染色
  于是我们重新来审视以下删除后的维护过程为什么要这么做:
  首先可以直接处理完毕的case有: case 1:  N  节点是根节点,直接删除即可case 4:  P  节点是红色,其他四个节点都是黑色,那么只需要将 P  节点染为黑色,S  节点染为红色,删除 N  节点即可case 6:当  N  和 S   和 C  是黑色,D  是红色时,将 P  和 S  旋转,使得 N  子树Black Height加一,而为了防止 P  节点是黑色时导致 D  子树的Black Height减一,我们将 S  节点改为 P  节点的颜色,此时相当于从右子树移动了一个黑色到左子树,为了保持平衡,我们将D  节点也染为黑色,这样就使左子树的Black Height加一,在移除 N  节点后,整棵树的Black Height不变
  合理地使用旋转和染色可以用来操控子树的Black Height,另外的三种情况就是想办法把旋转操作的五个关键节点变成可以直接处理的情况 case 2:这种情况的思路时让  P  的右子树也集体Black height减一,然后就可以把 N  子树减一的状态扩展到 P  子树上,从而向上寻求一个可以直接处理的解case 3:这种情况的主要目的是将子节点的红色转移到父节点上,从而进入case4、5、6 case 5:将红色节点从  C  转移到 D  上,从而进入case 6
  为什么不能直接染色更改?
  直接修改成红色可能打破role 3,所以通过旋转后,保证了修改节点的子节点一定是黑色,然后再修改颜色
  到这里红黑树的基本思想已经介绍完成了
  完全把这些情况和旋转、染色的意义理清楚还是花费了超出想象的篇幅,所以关于Linux源码的部分暂且就不再看了,其实现的原理都是基于红黑树罢

浅析中世纪欧洲城市卫生状况及应对措施中世纪,是贵族盛行的时代,是精致生活的重要发展时代。于此同时,中世纪也被称为最臭的时期之一。我们看到的,几乎是贵族们光鲜靓丽的一面实际上当时的街道是由粪便腐烂食物垃圾未清理的尸体等一个让死神都无可奈何的男人,他是谁?2002年5月31日,在韩国和日本联合举办的世界杯开幕当天,一位名叫乔治威尔斯的老人永远的离开了这个世界,这位老人看起来似乎并没有什么特殊的,但他却实实在在是一位让死神都无可奈何的四大文明古国只剩中国,老外为什么只有中国文明一直延续至今?在美国版的某乎上,有这样一个问题,美国网友是这样问的中国真的是唯一一个延续至今的古文明吗?还是说只有中国人自己这样认为的?其中最受欢迎的回答是这样说的,人们认为中国文明是唯一自我起孝庄13岁嫁给皇太极,辅佐顺治成就了康熙,为何死后37年不下葬她是一个神奇的女人,在丈夫死去失去屏障之后,忍辱负重,与各方势力周旋,翻转于政治的风头浪尖,为一个帝国开辟了伟大的事业做出了贡献,并成就了其孙儿千古一帝的美名。这个人便是孝庄太后,万历十五年读懂这些人物,就能读懂身边的牛人日常生活中,总会发现一些高人。他们深居简出,行踪不定,你很难猜测到他们的想法。这就是牛人。今天这本书,记载了历史上一些牛人。几千年过去了,他们依然被人们所记住。以下是书评部分历史还金国灭亡之时到底有多惨!可能超出你的想象北宋有多惨,金国灭亡时就有多惨!金哀宗被一刀劈成两半,皇后也被士兵任意糟蹋,还被画了下来,场面一度极其惨烈。公元1234年,蒙古和南宋的联合部队到达蔡州城下,在蒙宋联军的猛烈攻势下中国历史人物序列(三)大禹治水尧担任部落首领期间,中原大地连年发生水灾,成片良田。房屋。牲畜。人们,都糟到洪水侵害淹没。当年居住在崇地的一个小部落首领叫鲧的,奉了尧的指令去治理洪水。鲧用了八年多的时间与春秋齐相晏婴二桃杀三士,除秽荐良将齐景公为了恢复齐桓公的霸业,就把齐国内号称三杰的田开疆古冶子公孙捷这三个大力士拢在身边,倚为干将,委以重任。而实际上这三个人有勇无谋,横行朝廷,作威作福,使齐国朝野的贤臣都怕他们而史记宋微子世家(四宋襄公篇)愍公七年,齐桓公即位。九年,宋水,鲁使臧文仲往吊水。译文宋愍公七年(前685),齐桓公即位为齐国国君。宋愍公九年(前683),宋国发生水灾,鲁国派使臣臧文仲到宋国慰问。愍公自罪曰寡先织娘娘嫫母和先蚕娘娘嫘祖都是黄帝的妃子黄帝的另一位妃子嫫母也在中国服装纺织方面做出了巨大的贡献,跟貌若天仙的嫘祖不一样的是,她长着个大奔儿头,短短的下巴,臃肿的身体,黑黑的皮肤,其形象后来被用作驱鬼的魌(q)头,但其品正能量,历史故事郗公既郗鉴,在永嘉乱离时期,住在家乡,生活非常穷困,以至于经挨饿,家乡人因为他德高望重的缘故,大家轮流供他饭吃,郗公经常带着侄儿郗迈,外甥周翼两个小孩一同去吃饭。家乡人说丧乱时期,
一提到冬,自然会想到雪冬日絮语朱爱华一,每天站在窗前,看风踩过树枝,落叶,踩过路上蹒跚的老人有时我听见,阳光穿过折断意志的枝条翻越一座座山岭,滚落山谷时的不安有时,我听见雨水拍打落叶啪啪,啪啪!急切,焦澳大利亚弃赛或被罚,国际篮联已介入,中国男篮世界杯出线收利好最近中国男篮已经打败伊朗队,取得非常酣畅淋漓的胜利。本来打败伊朗队之后,国际篮联已经宣布重大好消息,他们确定中国队已经提前晋级世界杯的正赛。如此一来按照国际篮联的说法,中国队后续就我和人工智能聊了会,它说世界杯荷兰能夺冠现在,人工智能(AI)进化到了什么程度?机器是否拥有了像人一样的智能呢?随着时代的发展,AI可以把录音实时转成文字AI绘画能画出像人类一样的作品AI智能语音甚至能用话务员的声音给你聊聊西班牙的世界杯名单,意料之外吗?其实情理之中Hola,todos。11日晚,西班牙国家队公布了参加世界杯的26人大名单,如果你对拉莫斯德赫亚等球星的落选感到惊讶,或是对一些球员的入选感到疑惑,那就来跟小菲一起看看这份名单吧。世界杯32强分组一句话形势攻略,资深菜鸟球迷皆适用作为4年一度的足球乃至体育的饕餮盛宴,2022年的卡塔尔世界杯将在不久后的11月21日正式拉开帷幕。为方便资深与菜鸟球迷都能对世界杯参赛的32支球队的小组形势有着最简洁明了的了解。女人的盆腔炎多是寒湿引起,张仲景一个千年古方,散寒又祛脾湿有了性生活后,女性得盆腔炎的几率就会大大增加。如果不及时治疗,就会引起腹痛腰酸月经不调,甚至对女性正常妊娠造成障碍等。十个女人九个寒,女人的妇科病很多都是因为身体里的寒湿引起的,盆深圳痛经假经确诊可休1到2天痛经可以说是每个女孩子的噩梦了,腰酸,腹痛,行动不便,严重的时候甚至疼到大脑提片空白,但是只能硬撑着上学上班,针对委员程提出的关于保障女职工生理假的建议,深圳市人社局回复称,女职工空腹一定不能吃食物,牢记3不吃,3吃身体健康时间过得真快,立冬已经过去,寒冷的冬天也就意味着正式来,所以这个时候呢,一定要注意保暖以及饮食。特别是早餐这一顿,是非常关键的,空腹情况下千万不能乱吃。张文宏空腹记住三吃三不吃,长泰山队弃将挽救泰山!1米87!25岁,曾是戴琳和刘军帅的备胎北京时间11月14日,在河南队爆冷击败武汉三镇让山东泰山队独享了积分榜第1的宝座后,令山东泰山队球迷最不能忘记的河南队球员就是在武汉三镇门前暴力扫射进球的杨帅,他的这个进球不但让河梅西曾与恩里克争吵过,之后关系很好,他离开时我们告诉他留下直播吧11月14日讯梅西接受JorgeValdano采访,谈到了自己的巴萨生涯,包括与恩里克的关系。梅西与恩里克在2015年夺得三冠王,但两人在对阵皇家社会的比赛有过争吵传闻。对于女排联赛!龚翔宇21分,吴梦洁25分,江苏女排4连胜领跑202223赛季中国女排超级联赛,11月14日B组迎来第五轮角逐,这个比赛日还是三场较量。江苏女排击败福建女排,斩获四连胜领跑积分榜。另外,广东女排和河南女排本轮也获胜,上海女排本