本文首先介绍系数扫描模式的初始化。
直接给出代码及相应的注释:
// scanning order table UInt* g_auiSigLastScan[ 3 ][ MAX_CU_DEPTH ]; //!< [pattern][depth] const UInt g_sigLastScan8x8[ 3 ][ 4 ] = { {0, 2, 1, 3}, //!< right-up diagonal {0, 1, 2, 3}, //!< horizontal {0, 2, 1, 3} //!< vertical }; UInt g_sigLastScanCG32x32[ 64 ];
Void initSigLastScan(UInt* pBuffD, UInt* pBuffH, UInt* pBuffV, Int iWidth, Int iHeight, Int iDepth) { const UInt uiNumScanPos = UInt( iWidth * iWidth ); UInt uiNextScanPos = 0; /* ** 在这里需要先作如下说明,以免对接下来代码中的一些处理会有疑惑。 ** 首先,在初始化时,总共有2x2,4x4,8x8,16x16,32x32,64x64,128x128这7种情况,当然,我们实际使用 ** 的就只有4x4,8x8,16x16,32x32这4种,其余的几种至少目前的draft中是不采用的,故重点关注这4种即可。 ** 其次,这段初始化代码是基于JCTVC-G644这个提案的,提案的具体内容请自行把这个提案下载下来阅读,这里 ** 不作详细介绍。 */ if( iWidth < 16 ) { UInt* pBuffTemp = pBuffD; if( iWidth == 8 ) { pBuffTemp = g_sigLastScanCG32x32; //!< 用于TU为32x32时的系数扫描,CG为Coefficient Group的缩写 } for( UInt uiScanLine = 0; uiNextScanPos < uiNumScanPos; uiScanLine++ ) { Int iPrimDim = Int( uiScanLine ); //!< uiScanLine为已经扫描过的反对角线数 Int iScndDim = 0; //!< 在某条反对角线上的计数 while( iPrimDim >= iWidth ) //!< 扫描的反对角线如果已经超过矩阵反对角线数的一半 { //!< 则根据该反对角线与反主对角线的距离,距离每增加1,则总元素数减1 iScndDim++; iPrimDim--; } while( iPrimDim >= 0 && iScndDim < iWidth ) //!< 设置矩阵中某一条反对角线上(左下到右上)的元素的序号 {//!< pBuffTemp赋值的原理:iPrimDim控制当前扫描到的元素的行数,iiScndDim控制该元素在反对角线上的序号 pBuffTemp[ uiNextScanPos ] = iPrimDim * iWidth + iScndDim ; uiNextScanPos++; iScndDim++; iPrimDim--; } } } if( iWidth > 4 ) { UInt uiNumBlkSide = iWidth >> 2; //!< 以4x4像素为一个单元 UInt uiNumBlks = uiNumBlkSide * uiNumBlkSide; //!< 单元数 UInt log2Blk = g_aucConvertToBit[ uiNumBlkSide ] + 1; for( UInt uiBlk = 0; uiBlk < uiNumBlks; uiBlk++ ) { uiNextScanPos = 0; UInt initBlkPos = g_auiSigLastScan[ SCAN_DIAG ][ log2Blk ][ uiBlk ]; //!< 以4x4块为单元的位置(序号) if( iWidth == 32 ) { initBlkPos = g_sigLastScanCG32x32[ uiBlk ]; //!< TU为32x32时,不会再在16个4x4块中进行up-right diamond扫描,而直接在整一个32x32中以4x4块为单元进行扫描 } UInt offsetY = initBlkPos / uiNumBlkSide; //!< 当前4x4块垂直方向的偏移量 UInt offsetX = initBlkPos - offsetY * uiNumBlkSide; //!< 当前4x4块水平方向的偏移量 UInt offsetD = 4 * ( offsetX + offsetY * iWidth ); //!< 当前4x4块第一个位置序号 UInt offsetScan = 16 * uiBlk; //!< 每一个4x4块包含了16个像素(即系数),用于给出当前4x4块第一个位置相对于第1个4x4块第一个位置的偏移量 for( UInt uiScanLine = 0; uiNextScanPos < 16; uiScanLine++ ) //!< 对每个4x4块进行扫描顺序的确定 { Int iPrimDim = Int( uiScanLine ); Int iScndDim = 0; while( iPrimDim >= 4 ) //!< 则根据该反对角线与反主对角线的距离,距离每增加1,则总元素数减1 { iScndDim++; iPrimDim--; } while( iPrimDim >= 0 && iScndDim < 4 ) //!< 设置矩阵中某一条反对角线上(左下到右上)的元素的序号 { pBuffD[ uiNextScanPos + offsetScan ] = iPrimDim * iWidth + iScndDim + offsetD; uiNextScanPos++; iScndDim++; iPrimDim--; } } } } UInt uiCnt = 0; if( iWidth > 2 ) {//!< 水平扫描模式 UInt numBlkSide = iWidth >> 2; for(Int blkY=0; blkY < numBlkSide; blkY++) //!< 以4x4块为单元,行优先 { for(Int blkX=0; blkX < numBlkSide; blkX++) { UInt offset = blkY * 4 * iWidth + blkX * 4; //!< 确定当前4x4块的第一个位置序号 for(Int y=0; y < 4; y++) //!< 对每个4x4块中的16个位置进行遍历,行优先 { for(Int x=0; x < 4; x++) { pBuffH[uiCnt] = y*iWidth + x + offset; uiCnt ++; } } } } //!< 垂直扫描模式 uiCnt = 0; for(Int blkX=0; blkX < numBlkSide; blkX++) //!< 以4x4块为单元,列优先 { for(Int blkY=0; blkY < numBlkSide; blkY++) { UInt offset = blkY * 4 * iWidth + blkX * 4; for(Int x=0; x < 4; x++) //!< //!< 对每个4x4块中的16个位置进行遍历,行优先 { for(Int y=0; y < 4; y++) { pBuffV[uiCnt] = y*iWidth + x + offset; uiCnt ++; } } } //!< for(Int blkY=0; blkY < numBlkSide; blkY++) } //!< for(Int blkX=0; blkX < numBlkSide; blkX++) } //!< if( iWidth > 2 ) else //!< if( iWidth <= 2 ) { //!< Horizontal scan pattern for(Int iY=0; iY < iHeight; iY++) { for(Int iX=0; iX < iWidth; iX++) { pBuffH[uiCnt] = iY*iWidth + iX; uiCnt ++; } } //!< Vertical scan pattern uiCnt = 0; for(Int iX=0; iX < iWidth; iX++) { for(Int iY=0; iY < iHeight; iY++) { pBuffV[uiCnt] = iY*iWidth + iX; uiCnt ++; } } } //!< else //!< if( iWidth <= 2 ) }
栈的定义
栈(Stack)是限制仅在表的一端进行插入和删除运算的线性表。
(1)通常称插入、删除的这一端为栈顶 (Top),另一端称为栈底 (Bottom)。
(2)当表中没有元素时称为空栈。
(3)栈为后进先出(Last In First Out)的线性表,简称为 LIFO 表。
栈的修改是按后进先出的原则进行。每次删除(退栈)的总是当前栈中"
最新"的元素,即最后插入(进栈)的元素,而最先插入的是被放在栈的底部,
要到最后才能删除。
【示例】元素是以a1,a2,…,an的顺序进栈,退栈的次序却是an,an-1,…,
a1。
2、栈的基本运算
(1)InitStack(S)
构造一个空栈S。
(2)StackEmpty(S)
判栈空。若S为空栈,则返回TRUE,否则返回FALSE。
(3)StackFull(S)
判栈满。若S为满栈,则返回TRUE,否则返回FALSE。
注意: 该运算只适用于栈的顺序存储结构。
(4)Push(S,x)
进栈。若栈S不满,则将元素x插入S的栈顶。
(5)Pop(S)
定义堆栈ADT
StackADT
package Stack;
public interface StackADT {
public void push(Object element);//压栈
public Object pop();//出栈
public boolean isEmpty();
public int size();
public Object peek();//返回栈顶对象的一个引用
public String toString();
}
链式实现:
在栈的一段添加和删除元素,在栈中维护一个指向栈顶的结点和一个count变量指示栈的大小:
private LinearNode top; //指向栈顶
private int count;//标记栈的大小
每次出栈和压栈在链表的表头:(也可以再表尾,实现方式不一样而已)
top--->元素1--->元素2--->元素3.........
实现(附带测试main):
LinkedStack
package Stack;
import Bag.LinearNode;
//为了重点来实现算法,将异常情况直接打印出然后退出程序,不再声明异常类
public class LinkedStack implements StackADT {
private LinearNode top; //指向栈顶
private int count;//标记栈的大小
public static void main(String[] args){
LinkedStack stack = new LinkedStack();
System.out.println("将
a) It’s done after the execution of EACH line of code.
b) It reclaims the memory of an object when on local variable references it directly, even when another referenced object links to it.
c) When it reclaims an object, it reclaims all the objects contained by the object. Notes does not allow free-floating objects that exist outside their container, or "owner" object. Documents, for example, must belong to a database. Items must belong to a document, and ACLEntries must belong to an ACL object.
Point a) ensures the efficient memory usage when a sub involves the iteration of a large number of Notes objects e.g. documents.
set view = db.GetView("$all") set doc = view.GetFirstDocument() while not (doc is nothing) ' do something... set doc = view.GetNextDocument(doc) wend
Point b) and c) are harmful when they work together.
dim s as new NotesSession dim entry as NotesEntry set entry = s.CurrentDatabase.ACL.GetFirstEntryThe entry object will be reclaimed right after the assignment statement is executed as the ACL object is not stored in any variable and thus destructed, which causes the child object ACLEntry to be reclaimed. The issue in this case can be fixed by storing the ACL object in a variable.
Another case is as below:
Sub Initialize Dim s As New NotesSession Dim view As NotesView Set view=TestObj() Print view.Name End Sub Function TestObj As NotesView Dim s As New NotesSession Dim db As NotesDatabase Set db=s.Getdatabase(s.Currentdatabase.Server, "log.nsf") Set TestObj=db.Getview("UsageByUser") End functionThe View object returned by the function TestObj is reclaimed before it can be used by the caller because the parent database log.nsf is reclaimed after the function ends. If the view is from the current database, it will keep alive, even if the current database object is not initialized in the caller. The current session and database objects keep alive until the whole program e.g. agent exits. To avoid the failure above, a global variable can be declared to hold the exterior database object.
Sub Initialize Dim s As New NotesSession ‘the following two lines are optional Dim db As NotesDatabase Set db=s.Currentdatabase Dim view As NotesView Set view=TestObj() Print view.Name End Sub Function TestObj As NotesView Dim s As New NotesSession Set TestObj=s.Currentdatabase.Getview("All") End function