霍夫曼编码是一种基于最小冗余编码的压缩算法。最小冗余编码是指,如果知道一组数据中符号出现的频率,就可以用一种特殊的方式来表示符号从而减少数据需要的存储空间。一种方法是使用较少的位对出现频率高的符号编码,用较多的位对出现频率低的符号编码。我们要意识到,一个符号不一定必须是文本字符,它可以是任何大小的数据,但往往它只占一个字节。
熵和最小冗余
每个数据集都有一定的信息量,这就是所谓的熵 。一组数据的熵是数据中每个符号熵的总和 。符号z的熵S定义为:
Sz = -lg2 Pz
其中,Pz 就数据集中z出现的频率 。来看一个例子,如果z在有32个符号的数据集中出现了8次,也就是1/4的概率,那么z的熵就是:
-lg 2 (1/4) = 2位
这意味着如果用超过两位的数来表示z将是一种浪费。如果在一般情况下用一个字节(即8位)来表示一个符号,那么在这种情况下使用压缩算法可以大幅减小数据的容量。
下表展示如何计算一个有72个数据实例熵的例子(其中有5个不同的符号)。要做到这一点,需将每个字符的熵相加。以U为例,它在数据集中出现了12次,所以每个U的实例的熵计算如下:
符号
概率
每个实例的熵
总的熵
U
12/72
2.584 963
31.019 55
V
18/72
2.000 000
36.000 00
W
7/72
3.362 570
23.537 99
X
15/72
2.263 034
33.945 52
Y
20/72
1.847 997
36.959 94
-lg2 (12/72) = 2.584 963 位
由于U在数据中出现了12次,因此整个数据的熵为:
2.584 963 * 12 = 31.019 55 位
为了计算数据集整体的熵,将每个字符所贡献的熵相加。 每个字符的熵在表中已经计算出来了:
31.019 55 + 36.000 00 + 23.537 99 + 33.945 52 + 36.959 94 = 161.463 00 位
如果使用8位来表示每个符号,需要72 * 8 = 576位的空间,所以理论上来说,可以最多将此数据压缩:
1 - (161.463 000/576) = 72%
构造霍夫曼树
霍夫曼编码展现了一种基于熵的数据近似的最佳表现形式 。它首先生成一个称为霍夫曼树的数据结构,霍夫曼树本身是一棵二叉树,用它来生成霍夫曼编码。霍夫曼编码是用来表示数据集合中符号的编码,用这种编码的方式达到数据压缩的目的。 然而,霍夫曼编码的压缩结果往往只能接近于数据的熵,因为符号的熵往往是有小数位的,而在实际中,霍夫曼编码所用的位数不可能有小数位,所以有些代码会超过实际最优的代码位数。
下图展示了用上表中的数据来构建一棵霍夫曼树的过程。构建的过程往往是从叶子结点向上进行。首先,将每个符号和频率放到它自身的树中(步骤1) 。然后,将两个频率最小的根结点的树合并,并将其频率之和放到树的新结点中(步骤2) 。这个过程反复持续下去,直到最后只剩下一棵树(这棵树就是霍夫曼树,步骤5) 。霍夫曼的根结点包含数据中符号的总个数,它的叶子结点包含原始的符号和符号的频率 。由于霍夫曼编码就是在不断寻找两棵最适合合并的树,因此它是贪婪算法的一个很好的例子。
压缩和解压缩数据
建立一棵霍夫曼树是数据压缩和解压缩的一部分。
用霍夫曼树压缩数据,给定一个具体的符号 ,从树的根开始,然后沿着树的叶向叶子结点追踪。在向下追踪的过程中,当向左分支移动时,向当前编码的末尾追加0;当向右移动时,向当前编码的末尾追加1。 在上图中,追踪“U”的霍夫曼编码,首先向右移动(1),然后向左移动(10),然后再向右(101)。图中符号的霍夫曼编码分别为:
U=101,V=01,W=100,X=00,Y=11
要解压缩用霍夫曼树编码的数据,要一位一位地读取压缩数据。从树的根开始,当在数据中遇到0时,向树的左分支移动;当遇到1时,向右分支移动。一旦到达一个叶子结点就找到了符号。接着从头开始,重复以上过程,直到所有的压缩数据都找出。 用这种方法来解压缩数据是可能的,这是因为霍夫曼树是属于前缀树。前缀树是指一组代码中,任何一个编码都不是另一个编码的前缀。这就保证了编码被解码时不会有多义性。例如,“V”的编码是01,01不会是任何其他编码的前缀。因此,只要在压缩数据中碰到了01,就可以确定它表示的符号是“V”。
霍夫曼编码的效率
为了确定霍夫曼编码降低了多大容量的存储空间,首先要计算每个符号出现的次数与其编码位数的乘积,然后将其求和 。所以,上表中压缩后的数据的大小为:
12*3 + 18*2 + 7*3 + 15*2 +20*2 = 163位
假设不使用压缩算法的72个字符均用8位表示,那么其总共所占的数据大小为576位,所以其压缩比计算如下:
1 - (163/576)=71.7%
再次强调的是,在实际中无法用小数来表示霍夫曼编码,所以在很多情况下这个压缩比并没有数据的熵效果那么好。但也非常接近于最佳压缩比。
在通常情况下,霍夫曼编码并不是最高效的压缩方法,但它压缩和解压缩的速度非常快。一般来说,造成霍夫曼编码比较耗时的原因是它需要扫描两次数据:一次用来计算频率;另一次才是用来压缩数据。而解压缩数据非常高效,因为解码每个符号的序列只需要扫描一次霍夫曼树。
霍夫曼编码的接口定义
huffman_compress
int huffman_compress(const unsigned char *original, unsigned char **compressed, int size);
返回值 :如果数据压缩成功,返回压缩后数据的字节数;否则返回-1。
描述 :用霍夫曼编码的方法压缩缓冲区original中的数据,original包含size字节的空间。压缩后的数据存入缓冲区compressed中。由于函数调用者并不知道compressed需要多大的空间,因此需要通过函数调用malloc来动态分配存储空间。当这块存储空间不再使用时,由调用者调用函数free来释放空间。
复杂度 :O(n),其中n代表原始数据中符号的个数。
huffman_uncompress
int huffman_uncompress(const unsigned char *compressed, unsigned char **original);
返回值 :如果解压缩成功,返回恢复后数据的字节数;否则返回-1。
描述 :用霍夫曼的方法解压缩缓冲区compressed中的数据。假定缓冲区包含的数据是由Huffman_compress压缩产生的。恢复后的数据存入缓冲区original中。由于函数调用者并不知道original需要多大的空间 ,因此要通过函数调用malloc来动态分配存储空间。当这块存储空间不再使用时,由调用者调用free来释放空间。
复杂度 :O(n),其中n是原始数据中符号的个数。
霍夫曼编码的分析与实现
通过霍夫曼编码,在压缩过程中,我们将符号按照霍夫曼树进行编码从而压缩数据。在解压缩时,重建压缩过程中的霍夫曼树,同时将编码解码成符号本身。在本节介绍的实现过程中,一个原始符号都是用一个字节表示。
huffman_compress
huffman_compress操作使用霍夫曼编码来压缩数据。首先,它扫描数据,确定每个符号出现的频率。将频率存放到数组freqs中。完成对数据的扫描后,频率得到一定程度的缩放,因此它们可以只用一个字节来表示。当确定数据中某个符号的最大出现频率,并且相应确定其他频率后,这个扫描过程结束。由于数据中没有出现的符号,应该只是频率值为0的符号,所以执行一个简单的测试来确保当任何非0频率值其缩减为小于1时,最终应该将其值设为1而不是0。
一旦计算出了所有的频率,就调用函数build_tree来建立霍夫曼树。此函数首先将数据中至少出现过一次的符号插入优先队列中(实际上是一棵二叉树)。树中的结点由数据结构HuffNode定义。此结构包含两个成员:symbol为数据中的符号(仅在叶子结点中使用);freq为频率。每棵树初始状态下只包含一个结点,此结点存储一个符号和它的缩放频率(就像在数据freqs中记录和缩放的一样)。
要建立霍夫曼树,通过优先队列用一个循环对树做size-1次合并。在每次迭代过程中,两次调用pqueue_extract来提取根结点频率最小的两棵二叉树。然后,将两棵树合并到一棵新树中,将两棵树的频率和存放到新树的根结点中,接着把新的树保存回优先级队列中。这个过程会一直持续下去,直到size-1次迭代完成,此时优先级队列中只有一棵二叉树,这就是霍夫曼树。
利用上一步建立的霍夫曼树,调用函数build_table来建立一个霍夫曼编码表,此表指明每个符号的编码。表中每个条目都是一个HuffCode结构。此结构包含3个成员:used是一个默认为1的标志位,它指示此条目是否已经存放一个代码;code是存放在条目中的霍夫曼编码;size是编码包含的位数。每个编码都是一个短整数,因为可以证明当所有的频率调整到可以用一个字节来表示时,没有编码会大于16位。
使用一个有序的遍历方法来遍历霍夫曼树,从而构建这个表。在每次执行build_table的过程中,code 记录当前生成的编码,size保存编码的位数。在遍历树时,每当选择左分支时,将0追加到编码的末尾中;每当选择右分支时,将1追加到编码的末尾中。一旦到达一个叶子结点,就将霍夫曼编码存放到编码表合适的条目中。在存放每个编码的同时,调用函数htons,以确保编码是以大端字节格式存放。这一步非常重要,因为在下一步生成压缩数据时需要用大端格式,同样在解压缩过程中也需要大端格式。
在产生压缩数据的同时,使用ipos来保存原始数据中正在处理的当前字节,并用opos来保存向压缩数据缓冲区写入的当前位。首先,缩写一个头文件,这有助于在huffman_uncompress中重建霍夫曼树。这个头文件包含一个四字节的值,表示待编码的符号个数,后面跟着的是所有256个可能的符号出现的缩放频率,也包括0。最后对数据编码,一次读取一个符号,在表中查找到它的霍夫曼编码,并将每个编码存放到压缩缓冲区中。在压缩缓冲区中为每个字节分配空间。
huffman_compress的时间复杂度为O(n),其中n是原始数据中符号的数量。
huffman_uncompress
huffman_uncompress操作解压缩由huffman_compress压缩的数据。首先,此操作读取追加到压缩数据的头。回想一下,头的前4个字节包含编码符号的数量。这个值存放在size中。接下来的256个字节包含所有符号的缩放频率。
利用存放在头中的信息,调用build_tree重建压缩过程中用到的霍夫曼树。一旦重建了树,接下来就要生成已恢复数据的缓冲区。要做到这一点,从压缩数据中逐位读取数据。从霍夫曼树的根开始,只要遇到位数0,就选择左分支;只要遇到位数1,就选择右分支。一旦到达叶子结点,就获取一个符号的霍夫曼编码。解码符号存储在叶子中。所以, 将此符号写入已恢复数据的缓冲区中。写入数据之后,重新回到根部,然后重复以上过程。使用ipos来保存向压缩数据缓冲区写入的当前位,并用opos来保存写入恢复缓冲区中的当前字节。一旦opos到达size,就从原始数据中生成了所有的符号。
huffman_uncompress的时间复杂度为O(n)。其中n是原始数据中符号的数量。这是因为对每个要解码符号来说,在霍夫曼树中向下寻找的深度是一个有界常量,这个常量依赖于数据中不同符号的数量。在本节的实现中,这个常量是256.建立霍夫曼树的过程不影响huffman_uncompress的复杂度,因为这个过程只依赖于数据中不同符号的个数。
示例:霍夫曼编码的实现文件
/* huffman.c */
#include
#include in.h>
#include
#include <string .h>
#include " bit.h "
#include " bitree.h "
#include " compress.h "
#include " pqueue.h "
/* compare_freq 比较树中霍夫曼节点的频率 */
static int compare_freq(const void *tree1,const void *tree2)
{
HuffNode *root1,root2;
/* 比较两棵二叉树根结点中所存储的频率大小 */
root1 = (HuffNode *)bitree_data(bitree_root((const BiTree *)tree1));
root2 = (HuffNode *)bitree_data(bitree_root((const BiTree *)tree2));
if (root1->freq < root2->freq)
return 1 ;
else if (root1->freq > root2->freq)
return -1 ;
else return 0 ;
}
/* destroy_tree 消毁二叉树 */
static void destroy_tree(void *tree)
{
/* 从优先级队列中消毁并释放一棵二叉树 */
bitree_destroy(tree);
free (tree);
return ;
}
/* buile_tree 构建霍夫曼树,每棵树初始只包含一个根结点 */
static int bulid_tree(int *freqs,BiTree **tree)
{
BiTree *init,
*merge,
*left,
*right;
PQueue pqueue;
HuffNode *data;
int size,c;
/* 初始化二叉树优先级队列 */
*tree = NULL;
pqueue_init( &pqueue,compare_freq,destroy_tree);
for (c=0 ; c<=UCHAR_MAX; c++)
{
if (freqs[c] != 0 )
{
/* 建立当前字符及频率的二叉树 */
if ((init = (BiTree *)malloc (sizeof (BiTree))) == NULL)
{
pqueue_destroy( &pqueue);
return -1 ;
}
bitree_init(init, free );
if ((data = (HuffNode*)malloc (sizeof (HuffNode))) == NULL)
{
pqueue_destroy( &pqueue);
return -1 ;
}
data ->symbol = c;
data ->freq = freqs[c];
if (bitree_ins_left(init,NULL,data) != 0 )
{
free (data);
bitree_destroy(init);
free (init);
pqueue_destroy( &pqueue);
return -1 ;
}
/* 将二叉树插入优先队列 */
if (pqueue_insert(&pqueue,init) != 0 )
{
bitree_destroy(init);
free (init);
pqueue_destroy( &pqueue);
return -1 ;
}
}
}
/* 通过两两合并优先队列中的二叉树来构建霍夫曼树 */
for (c=1 ; c<=size-1 ; c++)
{
/* 为合并后的树分配空间 */
if ((merge = (BiTree *)malloc (sizeof (BiTree))) == NULL)
{
pqueue_destroy( &pqueue);
return -1 ;
}
/* 提取队列中拥有最小频率的两棵树 */
if (pqueue_extract(&pqueue,(void **)&left) != 0 )
{
pqueue_destroy( &pqueue);
free (merge);
return -1 ;
}
if (pqueue_extract(&pqueue,(void **)right) !=0 )
{
pqueue_destroy( &pqueue);
free (merge);
return -1 ;
}
/* 分配新产生霍夫曼结点的空间 */
if ((data = (HuffNode *)malloc (sizeof (HuffNode))) == NULL)
{
pqueue_destroy( &pqueue);
free (merge);
return -1 ;
}
memset(data, 0 ,sizeof (HuffNode));
/* 求和前面提取的两棵树的频率 */
data ->freq = ((HuffNode *)bitree_data(bitree_root(left)))->freq +
((HuffNode *)bitree_data(bitree_root(right)))->freq;
/* 合并left、right两棵树 */
if (bitree_merge(merge,left,right,data) != 0 )
{
pqueue_destroy( &pqueue);
free (merge);
return -1 ;
}
/* 把合并后的树插入到优先级队列中,并释放left、right棵树 */
if (pqueue_insert(&pqueue,merge) != 0 )
{
pqueue_destroy( &pqueue);
bitree_destroy(merge);
free (merge);
return -1 ;
}
free (left);
free (right);
}
/* 优先队列中的最后一棵树即是霍夫曼树 */
if (pqueue_extract(&pqueue,(void **)tree) != 0 )
{
pqueue_destroy( &pqueue);
return -1 ;
}
else
{
pqueue_destroy( &pqueue);
}
return 0 ;
}
/* build_table 建立霍夫曼编码表 */
static void build_table(BiTreeNode *node, unsigned short code, unsigned char size, HuffCode *table)
{
if (!bitree_is_eob(node))
{
if (!bitree_is_eob(bitree_left(node)))
{
/* 向左移动,并将0追加到当前代码中 */
build_table(bitree_left(node),code <<1 ,size+1 ,table);
}
if (!bitree_is_eob(bitree_right(node)))
{
/* 向右移动,并将1追加到当前代码中 */
build_table(bitee_right(node),(code <<1 ) | 0x0001 ,size+1 ,table);
}
if (bitree_is_eob(bitree_left(node)) && bitree_is_eob(bitree_right(node)))
{
/* 确保当前代码是大端格式 */
code = htons(code);
/* 将当前代码分配给叶子结点中的符号 */
table[((HuffNode *)bitree_data(node))->symbol].used = 1 ;
table[((HuffNode *)bitree_data(node))->symbol].code = code;
table[((HuffNode *)bitree_data(node))->symbol].size = size;
}
}
return ;
}
/* huffman_compress 霍夫曼压缩 */
int huffman_compress(const unsigned char *original, unsigned char **compressed, int size)
{
BiTree *tree;
HuffCode table[UCHAR_MAX + 1 ];
int freqs[UCHAR_MAX + 1 ],
max,
scale,
hsize,
ipos,opos,cpos,
c,i;
unsigned *comp,*temp;
/* 初始化,没有压缩数据的缓冲区 */
*compressed = NULL;
/* 获取原始数据中每个符号的频率 */
for (c=0 ; c <= UCHAR_MAX; c++)
freqs[c] = 0 ;
ipos = 0 ;
if (size > 0 )
{
while (ipos < size)
{
freqs[original[ipos]] ++;
ipos ++;
}
}
/* 将频率缩放到一个字节 */
max = UCHAR_MAX;
for (c=0 ; c<=UCHAR_MAX; c++)
{
if (freqs[c] > max)
max = freqs[c];
}
for (c=0 ; c <= UCHAR_MAX; c++)
{
scale = (int )(freqs[c] / ((double )max / (double )UCHAR_MAX));
if (scale == 0 && freqs[c] != 0 )
freqs[c] = 1 ;
else
freqs[c] = scale;
}
/* 建立霍夫曼树和编码表 */
if (build_tree(freqs,&tree) != 0 )
return -1 ;
for (c=0 ; c<=UCHAR_MAX; c++)
memset( &table[c],0 ,sizeof (HuffCode));
bulid_table(bitree_root(tree), 0x0000 , 0 , table);
bitree_destroy(tree);
free (tree);
/* 编写一个头代码 */
hsize = sizeof (int ) + (UNCHAR_MAX + 1 );
if ((comp = (unsigned char *)malloc (hsize)) == NULL)
return -1 ;
memcpy(comp, &size,sizeof (int ));
for (c=0 ; c<=UCHAR_MAX; c++)
comp[ sizeof (int ) + c] = (unsigned char )freqs[c];
/* 压缩数据 */
ipos = 0 ;
opos = hsize*8 ;
while (ipos < size)
{
/* 获取原始数据中的下一个字符 */
c = original[ipos];
/* 将字符对应的编码写入压缩数据的缓存中 */
for (i=0 ; i)
{
if (opos % 8 == 0 )
{
/* 为压缩数据的缓存区分配另一个字节 */
if ((temp = (unsigned char *)realloc (comp,(opos/8 )+1 )) == NULL)
{
free (comp);
return -1 ;
}
comp = temp;
}
cpos = (sizeof (short )*8 ) - table[c].size + i;
bit_set(comp, opos, bit_get((unsigned char *)&table[c].code,cpos));
opos ++;
}
ipos ++;
}
/* 指向压缩数据的缓冲区 */
*compressed = comp;
/* 返回压缩缓冲区中的字节数 */
return ((opos - 1 ) / 8 ) + 1 ;
}
/* huffman_uncompress 解压缩霍夫曼数据 */
int huffman_uncompress(const unsigned char *compressed, unsigned char **original)
{
BiTree *tree;
BiTreeNode *node;
int freqs[UCHAR_MAX + 1 ],
hsize,
size,
ipos,opos,
state,
c;
unsigned char *orig,*temp;
/* 初始化 */
*original = orig = NULL;
/* 从压缩数据缓冲区中获取头文件信息 */
hize = sizeof (int ) + (UCHAR_MAX + 1 );
memcpy( &size,compressed,sizeof (int ));
for (c=0 ; c<=UCHAR_MAX; c++)
freqs[c] = compressed[sizeof (int ) + c];
/* 重建前面压缩数据时的霍夫曼树 */
if (bulid_tree(freqs,&tree) != 0 )
return -1 ;
/* 解压缩数据 */
ipos = hsize * 8 ;
opos = 0 ;
node = bitree_root(tree);
while (opos < size)
{
/* 从压缩数据中获取位状态 */
state = bit_get(compressed,ipos);
ipos ++;
if (state == 0 )
{
/* 向左移动 */
if (bitree_is_eob(node) || bitree_is_eob(bitree_left(node)))
{
bitree_destroy(tree);
free (tree);
return -1 ;
}
else node = bitree_left(node);
}
else
{
/* 向右移动 */
if (bitree_is_eob(node) || bitree_is_eob(bitree_right(node)))
{
bitree_destroy(tree);
free (tree);
return -1 ;
}
else node = bitree_right(node);
}
if (bitree_is_eob(bitree_left(node)) && bitree_is_eob(bitree_right(node)))
{
/* 将叶子结点中的符号写入原始数据缓冲区 */
if (opos > 0 )
{
if ((temp = (unsigned char *)realloc (orig,opos+1 )) == NULL)
{
bitree_destroy(tree);
free (tree);
free (orig);
return -1 ;
}
orig = temp;
}
else
{
if ((orig = (unsigned char *)malloc (1 )) == NULL)
{
bitree_destroy(tree);
free (tree);
return -1 ;
}
}
orig[opos] = ((HuffNode *)bitree_data(node))->symbol;
opos ++;
/* 返回到霍夫曼树的顶部 */
node = bitree_root(tree);
}
}
bitree_destroy(tree);
free (tree);
/* 把向原始数据缓冲区 */
*original = orig;
/* 返回原始数据中的字节数 */
return opos;
}
你可能感兴趣的:(数据压缩算法---霍夫曼编码的分析与实现)
抢时机、抓重点,社会力量办学(园)综合整治在行动
社会力量办学
周末是各类辅导班开班办学的时间,培训教师、参训学生全部在场,能够全面反映办学机构的招生规模、管理水平等各方面的真实情况。区社会力量办学(园)综合管理办公室抓住这一有利时机,全体工作人员牺牲休息时间,到办学培训机构进行全面检查。工作人员对举办人指出不足以及整改建议对辅导机构的日常辅导情况进行检查工作人员认真检查相关资质在检查中,工作人员发现(存在问题:班额过大、招生人数与报备方案不一致;培训内容与营
儿童腺样体肥大
范晴母乳哺育指导
小孩子腺样体,和扁桃体肥大,通常情况这,夜里会打鼾,憋气。根据情况,稍作调整,增加松柏科精油以增加孩子身体含氧量,积极就医,配合精油调理,我会使用顺畅,丝柏或雪松,野橘,薰衣草交替家居熏香,丝柏,尤加利,顺畅,迷迭香各15滴混合椰子油5毫升滚珠涂抹患处,和脚底并按摩,一日数次视情况;乳香,丝柏,尤加利,顺畅,野橘,薄荷按摩脊柱,一周2,3次Amen女儿的腺样体肥大已经有一段时间了,晚上睡觉会打呼噜
小花园
smile丝唛小主
看网友的小花园,循着留给我的门号,摸着方向和路径就进去了,微信告诉到了,她从二楼下来开门,很惊讶我已站在后花园里~~~图片发自App图片发自App图片发自App图片发自App图片发自App图片发自App图片发自App图片发自App图片发自App
【雲洋讲品牌】如何创作品牌广告语? 品牌广告语创意的7大妙招!
李唐星辰
1、广告语必须是口语而非书面语!广告语是听觉思维是传播思维,一定要口语化表达!比如:地球人都知道!洗洗更健康!2、购买理由购买指令!且是品牌战略价值的演绎与表达!智慧爱让相处更自在!找灵感,喝乐淘!坤合园调理一级棒,不同体质不同样!怕上火,喝王老吉!3、心动词汇!与消费者里应外合,从消费者心智中寻找心动词语!人头马一开,好事自然来!4、为广告语寻找一个超级句式!句式就好比一个人的骨架,文字就好比血
第887篇:感恩星球之2020.9.10
罗文均
庚子年七月二十三星期四武汉晴1.我万分幸运并深深的感激,教师节这一天奖励自己把《琉璃》的大结局看完了,特别开心看到美好的结局,也特别喜欢一切以美好结局。2.我万分幸运并深深的感激,在老鹰群分享我从一个不会销售到能够连环成交20次到50次的分享,以及一天内让同一个人买单4次的经历,并截图为证,也跟从来没做过销售的小玉分享我一天被10000人拒绝后的原创分享带来的这个一天4次成交的故事,一天时间,只是
古代人为什么崇拜癞蛤蟆?癞蛤蟆象征着什么?
倒到糖我在
“癞蛤蟆想吃天鹅肉”现在就是一句骂人的话,可见在今天癞蛤蟆不是个好东西。但古人却一度把蛤蟆神圣化,成为神物,这又是出于一种怎样的脑洞呢?仔细说来,这也是有缘故的。首先、癞蛤蟆就是蟾蜍,属于蛙类,一产多子,当然很容易成为人们生殖信仰的崇敬对象。中国上古考古发掘出来的器皿,很多带有蛙文,足以为此证明。其次、蟾蜍寓意长生,这与蟾蜍冬眠的习性有关,在古人眼里犹如死而复生,生生不息。后来又有人把这份生生死死
2019.05.31闺女身上的疹子越来越多
lenal_cb96
时间:2019.05.31农历:四月廿七星期五天气晴转雨闺女三周三【早睡早起】昨晚22:30睡,今早5:00起床。【学习】1.学习谈股论经群内容2.团队YY语音频道早课:陈惠老师分享总部指导师培训心得。【读经长智慧】读经人:闺女、妈妈本周读经计划:《易经》需卦、讼卦,《成语接龙》8,《少年儿童诗词启蒙》61-70。《新概念英语》lesson11,《大易诗》。【为自己而读】《道德经》第17遍。今天单
2021-10-23
Reallove
今日小记今晚夜班,白天转班休息半天,由于昨晚睡得早,早上四点多就醒了睡不着。从早上醒来到晚上上班一直没睡,白天本来打算睡一下的,睡不着。把手机放在一边,躺了半天还是睡不着。由于最近限电,今晚上班时没开机,十点以后才开机升温,差不多十二点才开始,上半夜没事干却不困,到了下半夜这个点,有点困了。还好今晚片子好做,都挺稳定的。天气还有点冷,感觉已经进入冬天了,困了也不敢打瞌睡,怕感冒。强撑着,撑到明天早
【Python/Java/C++三种语言】20天拿下华为OD笔试之【位运算】2023B-出错的或电路【欧弟算法】全网注释最详细分类最全的华为OD真题
闭着眼睛学算法
最新华为OD真题 # 数学 # 位运算 算法 python java
文章目录题目描述与示例题目描述输入描述输出描述示例一输入输出说明示例二输入输出说明解题思路代码PythonJavaC++时空复杂度华为OD算法/大厂面试高频题算法练习冲刺训练题目描述与示例题目描述某生产门电路的厂商发现某一批次的或门电路不稳定,具体现象为计算两个二进制数的或操作时,第一个二进制数中某两个比特位会出现交换,交换的比特位置是随机的,但只交换这两个位,其他位不变。很明显,这个交换可能会影
《郡主腰软声甜,撩得世子脸红心跳》江黛李綦&全集目录-在线阅读
小说推书
《郡主腰软声甜,撩得世子脸红心跳》江黛李綦&全集目录-在线阅读主角:江黛李綦简介:江黛娇媚诱人,随意展露的风情便让诸多男儿午夜梦回,早起更衣。唯宁王二子李綦,对她诸多鄙夷。“江黛那般貌美,日日与她相处,你就不动心?”李綦冷哼:“蛇蝎美人,寡廉鲜耻,满腹心计,谁对她动心谁是狗!可以关注微信公众号【放心文楼】去回个书号【20】,即可免费阅读【郡主腰软声甜,撩得世子脸红心跳】小说全文!第9章江黛跟着大丫
吕卫花中原焦点学习初19期,坚持分享第四天
梓旭她妈好棒呀
夏虫不可语冰。或许谁都体会不到当时为什么说那样的话,做那样的事,站在当事人的立场考虑问题,体会其中的不易。或许人与人之间就会多点理解与体谅,少点误会与分歧。在工作中有时特别不理解领导的做法和说法,觉得他们的一言一行不靠谱,现在想想,或许我们站的高度不一样,考虑的不够全面,自己在自己的小圈子里思考问题,一般都是利己的思维。有时候觉得家人或者同事或者朋友的行为不可思议,有可能人家有难的苦衷,所以,不同
大数据平台(数据中台、数据中枢、数据湖、数据要素)建设方案
数字化建设方案
数字化转型 数据治理 主数据 数据仓库 大数据
大数据平台(数据中台、数据中枢、数据湖、数据要素)建设方案大数据平台(数据中台、数据中枢、数据湖、数据要素)建设方案项目背景和目标项目背景项目目标建设原则与策略数据中台架构设计整体架构设计思路数据采集层数据存储层数据计算层数据服务层数据中枢功能实现数据治理功能数据资产管理功能数据安全管控功能数据服务总线功能数据湖存储与计算方案数据湖存储架构设计数据湖计算框架选择数据湖应用场景分析数据湖安全与合规性
前期的魏武卒那么强,后期为何再也建立不起一支这么强悍的部队?
超超爱叨剧
在战国中前期群雄争夺霸权的战场上,“魏武卒”是震撼列国的一股力量。魏武卒是战国时期军事家吴起在魏文侯时代创建的一支军事力量。这支部队中的每个步兵都必须穿上重甲,背上重弩,在半天内跑完50公里。再加上军事家吴起极其严格的训练,终于把这支部队锻炼成了钢。吴起防守西河时,魏武卒发挥了强大的战力,多次以少胜多,一步一步地从西河要地打下了魏国霸业。在吴起统帅期间,这支魏武卒与战国列强经历了七十六场战争,其中
阅读《美国中小学教师》感悟
王Zhi
最近我读了《美国中小学教师》,由赵勇、王安琳和杨文中编著。感悟一,中美中小学教师工作比较,首先,从教师在教学中的角色和教学方法来看,中美教师之间存在着很大的差异,中国中小学教师的角色是知识的传授者,教师主要的任务是向学生传授知识,包括课程标准规定的课本中的内容,和知识,超过课程标准范围的有关知识,或成拓展性的知识,而美国教师,则更多的是充当学生的学习的组织者,促进者,和帮助者。从教学方法看,中国中
过于理性的生活
胡小悦
时间滴答滴答的走着我在沙发上躺了一会儿揉揉眼睛坐回书桌旁周围寂静无声最近总感觉生活在头脑的思维里过于理性在你的思考缺乏深度的时候是否反而阻碍了行动为向前一步找到了借口
做难而正确的事
留下故事的人
读《详谈左晖》人都是看别人的事容易,看自己的事难。芒格说世界上的诗事分三类,正确的,错误的太难的,我们一定要做正确的事,剩下的事不用干。我觉得我们这个难跟他那个太难是不太一样的。芒格说的太难是说目标过于有挑战性,而我们这个所谓的难主要是两个维度的状况,第一就是你要创造价值,如果不创造价值,仅仅获得结果,没有什么意义,第二是你在选择路径的时候要选择难的路。我觉得战略是一个确定地点的事情,首先你要知道
JAVA数组元素的遍历_Java数组元素的遍历
知更社区
JAVA数组元素的遍历
Java数组元素的遍历packagecom.wkcto.chapter03.demo01;importjava.util.Arrays;/***数组的定义,元素的访问与遍历*@author蛙课网**/publicclassTest01{publicstaticvoidmain(String[]args){//1)定义一个数组,存储5个int类型数据int[]data=newint[5];//定义数
培養自己
瘋人
不嬈艷,但要有氣質,培養自己的善良;不入俗,但要懂俗,培養自己出離的能力;不亂愛,但要懂愛,培養自己的慈悲能力;不亂講,但要懂因果,培養自己生命主人的能力;可以不信佛,但不能不明白無常,培養解脫心的能力!图片发自App
AJAX实时表单验证系统
三年九班蓝同学
本文还有配套的精品资源,点击获取简介:在网页开发中,"ajax验证表单"是一项关键任务,确保数据符合格式和规则,提升数据质量和用户体验。本应用通过使用JavaScript和XMLHttpRequest对象实现后台验证,无需页面刷新。它包括前端验证、事件处理、Ajax调用、服务器端处理、响应处理、用户体验和安全性等关键步骤,以jQuery库简化开发流程,创建高效、安全的表单验证系统。1.表单验证的重
出山偶遇
今生无悔清风徐
图片发自App难得出深山,偶遇农家园。桃花杏花艳,林处有炊烟。吠声阵阵传,邻里谈甚欢。漂泊在天涯,驻足思故园。遥想百花妍,妻母步期间,笑比桃花艳。佳境在人间,悠然观蓝天。图片发自App因工作原因难得出深山,偶遇一处农家园,草青青,桃花杏花开,景色很美,真是人间佳境――桃花园,甚是欢喜。驻足观赏,还真是溪水绕家园,时闻犬吠声,林处炊烟袅袅,好一派祥和的景象。突然想起远在家乡母亲、妻子,他们此时也在漫
2023手机赚钱靠谱软件有哪些?2023手机赚钱软件app排行榜前十名
氧惠好物
现在的手机赚钱平台可以说是非常多的,所以今天就来评测一些真正可以赚钱的手机软件排行榜前十名,都是正规靠谱的软件平台快来看看有没有适合自己的吧。1、高省APP高省APP是深耕返利行业多年的杭州长孚网络科技有限公司一手打造的,旨在为更多的小伙伴提供优质的返利服务。高省APP为用户提供超多的优惠福利。比如现在主流电商平台的商品几乎都有返利可以拿,像我们熟知的淘宝天猫、拼多多、唯品会、抖音、快手等电商平台
java 不四舍五入 保留,java保留两位小数(不四舍五入)
三年九班蓝同学
java 不四舍五入 保留
这篇文章主要介绍了java使double类型保留两位小数的方法,大家参考使用吧复制代码代码如下:mportjava.text.DecimalFormat;DecimalFormatdf=newDecimalFormat("######0.00");doubled1=3.23456doubled2=0.0;doubled3=2.0;df.format(d1);df.format(d2);df.for
学做蛋炒饭。
元气雨蕉
今天晚上妈妈准备教我做蛋炒饭,我听了特别开心,妈妈说前提是你必须把数学作业的几道题做完,于是我赶紧跑过去仔仔细细的做了梁老师留的几道题。过了大约十多分钟,我把数学题做完了,我终于可以开始学做蛋炒饭了。这个蛋炒饭很简单,首先需要准备材料。准备的材料有:小油菜、鸡蛋、肠、葱、胡萝卜、肉丁……只需要把这些东西切成块块就可以了。这些材料五颜六色的,像一朵朵美丽的小花朵。首先先把材料准备好,然后将葱、小油菜
C#中两个问号的含义
weixin_30363981
测试
stringstrParam=Request.Params["param"]??"";取??左边的值,如果??左边的值为null则取右边的值转载于:https://www.cnblogs.com/shadowtale/archive/2012/10/19/2731152.html
国庆篇
易州
说到国庆节,第一时间想到的那肯定是七天的长假和阅兵了,因为阅兵式展现我们民族的最好仪式,我不禁想到阅兵仪式时的致辞:看,我们威武的军队走过来了,英雄的血肉凝成中国军人的铮铮铁骨,英雄的精神聚起人民军队的赤胆忠魂。光荣传统,世代相传,人民军队,威名远扬!时光流逝,岁月如梭,人民军队的英雄气概是奔腾不息的江河,激越澎湃,浩浩荡荡!21世纪中国的钢铁雄师整装列队,接受祖国和人民的检阅。70门礼炮齐整地排
「 网络安全常用术语解读 」同源策略SOP详解:没有SOP就没有隐私
全栈安全
安全术语 web安全 安全术语
同源策略可保护用户的隐私和数据安全,防止恶意网站通过跨域请求(例如,通过JavaScript)访问或修改其他网站的数据。1.同源策略产生背景当浏览器从一个域发送一个HTTP请求到另一个域时,与另一个域相关的任何cookies,包括身份验证会话cookie,也会作为请求的一部分发送。如果没有同源策略,如果你访问一个恶意网站,该网站将能够读取你的电子邮件、私人消息等。2.同源策略定义同源策略(Same
SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件
暗雪之格
Spring spring boot 数据库 jar java-ee
SpringBoot整合H2数据库并将其打包成jar包、转换成exe文件H2是一个用Java开发的嵌入式数据库,它的主要特性使其成为嵌入式应用程序的理想选择。H2仅是一个类库,可以直接嵌入到应用项目中,而无需独立安装客户端和服务器端。常用开源数据库常用的开源数据库包括H2、Derby、HSQLDB、MySQL和PostgreSQL。相比之下,H2和HSQLDB非常适合作为嵌入式数据库使用,而其他数
顺序表(SequenceList)数据结构的基本操作实现详解
SuchABigBug
C语言 数据结构 链表 c语言
目录一、前言二、整体设计框架三、函数实现1.SeqListInit2.SeqListDestory3.SeqListCheckCapacity4.SeqListPushBack(尾插)5.SeqListPopBack(尾删)6.SeqListPushFront(头插)7.SeqListPopFront(头删)8.SeqlistFind9.SeqListInsert(任意位置插入)9.SeqList
218 因为相信,所以看见
回归自己的成长
#每日精进218/36520200805因为相信,所以看见,前路漫漫,用努力去践行,你值得拥有精彩,遇见各自的高光时刻。每天三件事1.工作事项:生产员工人体工程学培训;公众号协助;培训表单;瑜伽、健身拍照宣传;外训沟通;新项目人员策略;新员工入职培训协调;知识产权体系培训协调;车间员工试用期管理。2.陪伴家人:一起晚餐,做作业,聊天,玩耍洗刷。3.学习成长:早起,运动,冥想,专业学习,每日精进,英
善行的四个层次
田无疆
人们行善,大体分为四个层次:顺风为善,在本意上可能没打算做利众的善行,只是因为在做自己事情的时候,带来了一个良好的副产品,居然让众人都得到了好处。跟风行善,这一种是因为社会舆论导向的所成,不管是从教育还是舆论,都让我们互帮互助,用善心温暖世界。在绝大部分人心里,都存在着这样一种是非观,从而导致人们会在不太费劲的情况下,去做一些善行。这一部分人,他们并不明白为什么要去帮助他人,体会不到施善的快乐。是
分享100个最新免费的高匿HTTP代理IP
mcj8089
代理IP 代理服务器 匿名代理 免费代理IP 最新代理IP
推荐两个代理IP网站:
1. 全网代理IP:http://proxy.goubanjia.com/
2. 敲代码免费IP:http://ip.qiaodm.com/
120.198.243.130:80,中国/广东省
58.251.78.71:8088,中国/广东省
183.207.228.22:83,中国/
mysql高级特性之数据分区
annan211
java 数据结构 mongodb 分区 mysql
mysql高级特性
1 以存储引擎的角度分析,分区表和物理表没有区别。是按照一定的规则将数据分别存储的逻辑设计。器底层是由多个物理字表组成。
2 分区的原理
分区表由多个相关的底层表实现,这些底层表也是由句柄对象表示,所以我们可以直接访问各个分区。存储引擎管理分区的各个底层
表和管理普通表一样(所有底层表都必须使用相同的存储引擎),分区表的索引只是
JS采用正则表达式简单获取URL地址栏参数
chiangfai
js 地址栏参数获取
GetUrlParam:function GetUrlParam(param){
var reg = new RegExp("(^|&)"+ param +"=([^&]*)(&|$)");
var r = window.location.search.substr(1).match(reg);
if(r!=null
怎样将数据表拷贝到powerdesigner (本地数据库表)
Array_06
powerDesigner
==================================================
1、打开PowerDesigner12,在菜单中按照如下方式进行操作
file->Reverse Engineer->DataBase
点击后,弹出 New Physical Data Model 的对话框
2、在General选项卡中
Model name:模板名字,自
logbackのhelloworld
飞翔的马甲
日志 logback
一、概述
1.日志是啥?
当我是个逗比的时候我是这么理解的:log.debug()代替了system.out.print();
当我项目工作时,以为是一堆得.log文件。
这两天项目发布新版本,比较轻松,决定好好地研究下日志以及logback。
传送门1:日志的作用与方法:
http://www.infoq.com/cn/articles/why-and-how-log
上面的作
新浪微博爬虫模拟登陆
随意而生
新浪微博
转载自:http://hi.baidu.com/erliang20088/item/251db4b040b8ce58ba0e1235
近来由于毕设需要,重新修改了新浪微博爬虫废了不少劲,希望下边的总结能够帮助后来的同学们。
现行版的模拟登陆与以前相比,最大的改动在于cookie获取时候的模拟url的请求
synchronized
香水浓
java thread
Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。然而,当一个线程访问object的一个加锁代码块时,另一个线程仍然
maven 简单实用教程
AdyZhang
maven
1. Maven介绍 1.1. 简介 java编写的用于构建系统的自动化工具。目前版本是2.0.9,注意maven2和maven1有很大区别,阅读第三方文档时需要区分版本。 1.2. Maven资源 见官方网站;The 5 minute test,官方简易入门文档;Getting Started Tutorial,官方入门文档;Build Coo
Android 通过 intent传值获得null
aijuans
android
我在通过intent 获得传递兑现过的时候报错,空指针,我是getMap方法进行传值,代码如下 1 2 3 4 5 6 7 8 9
public
void
getMap(View view){
Intent i =
apache 做代理 报如下错误:The proxy server received an invalid response from an upstream
baalwolf
response
网站配置是apache+tomcat,tomcat没有报错,apache报错是:
The proxy server received an invalid response from an upstream server. The proxy server could not handle the request GET /. Reason: Error reading fr
Tomcat6 内存和线程配置
BigBird2012
tomcat6
1、修改启动时内存参数、并指定JVM时区 (在windows server 2008 下时间少了8个小时)
在Tomcat上运行j2ee项目代码时,经常会出现内存溢出的情况,解决办法是在系统参数中增加系统参数:
window下, 在catalina.bat最前面
set JAVA_OPTS=-XX:PermSize=64M -XX:MaxPermSize=128m -Xms5
Karam与TDD
bijian1013
Karam TDD
一.TDD
测试驱动开发(Test-Driven Development,TDD)是一种敏捷(AGILE)开发方法论,它把开发流程倒转了过来,在进行代码实现之前,首先保证编写测试用例,从而用测试来驱动开发(而不是把测试作为一项验证工具来使用)。
TDD的原则很简单:
a.只有当某个
[Zookeeper学习笔记之七]Zookeeper源代码分析之Zookeeper.States
bit1129
zookeeper
public enum States {
CONNECTING, //Zookeeper服务器不可用,客户端处于尝试链接状态
ASSOCIATING, //???
CONNECTED, //链接建立,可以与Zookeeper服务器正常通信
CONNECTEDREADONLY, //处于只读状态的链接状态,只读模式可以在
【Scala十四】Scala核心八:闭包
bit1129
scala
Free variable A free variable of an expression is a variable that’s used inside the expression but not defined inside the expression. For instance, in the function literal expression (x: Int) => (x
android发送json并解析返回json
ronin47
android
package com.http.test;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import
一份IT实习生的总结
brotherlamp
PHP php资料 php教程 php培训 php视频
今天突然发现在不知不觉中自己已经实习了 3 个月了,现在可能不算是真正意义上的实习吧,因为现在自己才大三,在这边撸代码的同时还要考虑到学校的功课跟期末考试。让我震惊的是,我完全想不到在这 3 个月里我到底学到了什么,这是一件多么悲催的事情啊。同时我对我应该 get 到什么新技能也很迷茫。所以今晚还是总结下把,让自己在接下来的实习生活有更加明确的方向。最后感谢工作室给我们几个人这个机会让我们提前出来
据说是2012年10月人人网校招的一道笔试题-给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 将重物放到天平左侧,问在两边如何添加砝码
bylijinnan
java
public class ScalesBalance {
/**
* 题目:
* 给出一个重物重量为X,另外提供的小砝码重量分别为1,3,9。。。3^N。 (假设N无限大,但一种重量的砝码只有一个)
* 将重物放到天平左侧,问在两边如何添加砝码使两边平衡
*
* 分析:
* 三进制
* 我们约定括号表示里面的数是三进制,例如 47=(1202
dom4j最常用最简单的方法
chiangfai
dom4j
要使用dom4j读写XML文档,需要先下载dom4j包,dom4j官方网站在 http://www.dom4j.org/目前最新dom4j包下载地址:http://nchc.dl.sourceforge.net/sourceforge/dom4j/dom4j-1.6.1.zip
解开后有两个包,仅操作XML文档的话把dom4j-1.6.1.jar加入工程就可以了,如果需要使用XPath的话还需要
简单HBase笔记
chenchao051
hbase
一、Client-side write buffer 客户端缓存请求 描述:可以缓存客户端的请求,以此来减少RPC的次数,但是缓存只是被存在一个ArrayList中,所以多线程访问时不安全的。 可以使用getWriteBuffer()方法来取得客户端缓存中的数据。 默认关闭。 二、Scan的Caching 描述: next( )方法请求一行就要使用一次RPC,即使
mysqldump导出时出现when doing LOCK TABLES
daizj
mysql mysqdump 导数据
执行 mysqldump -uxxx -pxxx -hxxx -Pxxxx database tablename > tablename.sql
导出表时,会报
mysqldump: Got error: 1044: Access denied for user 'xxx'@'xxx' to database 'xxx' when doing LOCK TABLES
解决
CSS渲染原理
dcj3sjt126com
Web
从事Web前端开发的人都与CSS打交道很多,有的人也许不知道css是怎么去工作的,写出来的css浏览器是怎么样去解析的呢?当这个成为我们提高css水平的一个瓶颈时,是否应该多了解一下呢?
一、浏览器的发展与CSS
《阿甘正传》台词
dcj3sjt126com
Part Ⅰ:
《阿甘正传》Forrest Gump经典中英文对白
Forrest: Hello! My names Forrest. Forrest Gump. You wanna Chocolate? I could eat about a million and a half othese. My momma always said life was like a box ochocol
Java处理JSON
dyy_gusi
json
Json在数据传输中很好用,原因是JSON 比 XML 更小、更快,更易解析。
在Java程序中,如何使用处理JSON,现在有很多工具可以处理,比较流行常用的是google的gson和alibaba的fastjson,具体使用如下:
1、读取json然后处理
class ReadJSON
{
public static void main(String[] args)
win7下nginx和php的配置
geeksun
nginx
1. 安装包准备
nginx : 从nginx.org下载nginx-1.8.0.zip
php: 从php.net下载php-5.6.10-Win32-VC11-x64.zip, php是免安装文件。
RunHiddenConsole: 用于隐藏命令行窗口
2. 配置
# java用8080端口做应用服务器,nginx反向代理到这个端口即可
p
基于2.8版本redis配置文件中文解释
hongtoushizi
redis
转载自: http://wangwei007.blog.51cto.com/68019/1548167
在Redis中直接启动redis-server服务时, 采用的是默认的配置文件。采用redis-server xxx.conf 这样的方式可以按照指定的配置文件来运行Redis服务。下面是Redis2.8.9的配置文
第五章 常用Lua开发库3-模板渲染
jinnianshilongnian
nginx lua
动态web网页开发是Web开发中一个常见的场景,比如像京东商品详情页,其页面逻辑是非常复杂的,需要使用模板技术来实现。而Lua中也有许多模板引擎,如目前我在使用的lua-resty-template,可以渲染很复杂的页面,借助LuaJIT其性能也是可以接受的。
如果学习过JavaEE中的servlet和JSP的话,应该知道JSP模板最终会被翻译成Servlet来执行;而lua-r
JZSearch大数据搜索引擎
颠覆者
JavaScript
系统简介:
大数据的特点有四个层面:第一,数据体量巨大。从TB级别,跃升到PB级别;第二,数据类型繁多。网络日志、视频、图片、地理位置信息等等。第三,价值密度低。以视频为例,连续不间断监控过程中,可能有用的数据仅仅有一两秒。第四,处理速度快。最后这一点也是和传统的数据挖掘技术有着本质的不同。业界将其归纳为4个“V”——Volume,Variety,Value,Velocity。大数据搜索引
10招让你成为杰出的Java程序员
pda158
java 编程 框架
如果你是一个热衷于技术的
Java 程序员, 那么下面的 10 个要点可以让你在众多 Java 开发人员中脱颖而出。
1. 拥有扎实的基础和深刻理解 OO 原则 对于 Java 程序员,深刻理解 Object Oriented Programming(面向对象编程)这一概念是必须的。没有 OOPS 的坚实基础,就领会不了像 Java 这些面向对象编程语言
tomcat之oracle连接池配置
小网客
oracle
tomcat版本7.0
配置oracle连接池方式:
修改tomcat的server.xml配置文件:
<GlobalNamingResources>
<Resource name="utermdatasource" auth="Container"
type="javax.sql.DataSou
Oracle 分页算法汇总
vipbooks
oracle sql 算法 .net
这是我找到的一些关于Oracle分页的算法,大家那里还有没有其他好的算法没?我们大家一起分享一下!
-- Oracle 分页算法一
select * from (
select page.*,rownum rn from (select * from help) page
-- 20 = (currentPag