list.c
来自「傅立叶变换和小波变换是图像压缩的重要工具。该代大戏是利用小波变换进行图像压缩。」· C语言 代码 · 共 1,356 行 · 第 1/2 页
C
1,356 行
assert(pRadixLink->Links);
memcpy(pRadixLink->Links, OldLinks, (sizeof(Link)*OldNumLinks));
//memset(pRadixLink->Links + OldNumLinks,0,(sizeof(Link)*(pRadixLink->NumLinks - OldNumLinks)));
MemFree(OldLinks);
}
void RadixLink_Destroy(RadixLink * pRadixLink)
{
int r;
assert(pRadixLink);
for(r=0;r<(pRadixLink->NumLinks);r++)
{
if ( pRadixLink->Links[r].Next )
Link_Destroy(pRadixLink->Links[r].Next);
}
MemFree(pRadixLink->Links);
MemFree(pRadixLink);
}
void RadixLink_Add(RadixLink *pRadixLink,void * Data,int Key)
{
assert(pRadixLink);
assert( Key >= 0 );
if ( Key >= pRadixLink->NumLinks )
RadixLink_Grow(pRadixLink, Key + (Key>>2) );
Link_Push(&(pRadixLink->Links[Key]),Data);
if ( Key < pRadixLink->Min ) pRadixLink->Min = Key;
if ( Key > pRadixLink->Max ) pRadixLink->Max = Key;
}
void * RadixLink_CutMax(RadixLink *pRadixLink,int *pKey)
{
Link * pLink;
pLink = (pRadixLink->Links) + (pRadixLink->Max);
while ( pRadixLink->Max >= 0 )
{
if ( pLink->Next )
{
if ( pKey ) *pKey = pRadixLink->Max;
return Link_Pop(pLink);
}
pRadixLink->Max --;
pLink --;
}
return NULL;
}
void * RadixLink_CutMin(RadixLink *pRadixLink,int *pKey)
{
Link * pLink;
pLink = (pRadixLink->Links) + (pRadixLink->Min);
while ( pRadixLink->Min < pRadixLink->NumLinks )
{
if ( pLink->Next )
{
if ( pKey ) *pKey = pRadixLink->Min;
return Link_Pop(pLink);
}
pRadixLink->Min ++;
pLink ++;
}
return NULL;
}
void * RadixLink_CutKey(RadixLink *pRadixLink,int Key)
{
assert(pRadixLink);
return Link_Pop(&(pRadixLink->Links[Key]));
}
/***** debug only : **********************/
void List_TimerReport(void)
{
#ifdef DO_TIMER
TIMER_REPORT(List_Ram);
TIMER_REPORT(List_RadixWalk);
TIMER_REPORT(List_RadixInit);
#endif
}
/*************************************************/
/**************************************************
Hash has separate Keys & Data
We use a single Circular list of all the nodes. We have
cappers of Hash = 0 and HASH_SIZE at the head and tail.
So a general hash looks like : (with HASH_SIZE == 7)
(Head)-->A--x->C--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
the brackets are hash buckets; little x's mean that hash bucket
has seen no nodes of its own hash, so it points to the next
larger hash's list.
to do a Get :
simply look at your current pointer and walk while hash == my hash
example : Get(Hash == 3)
we get node C : ok, test it
next is node E : not my hash, so I'm done
to do a delete :
simply cut your node, and point yourself to the next node.
example : Delete( Node C )
(Head)-->A--x--x--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
now hash bucket 3 points to node E
to do an add :
first you must take your current pointer and walk backwards until
the preceding node has a lower hash than you (see example later).
then simply add the new node before the current one and make yourself
point to the new one.
Example 1: Add an A:
bucket 1 already is in the right place
add before the old node :
+-A1
| |
(Head)-+ A2-x--x--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
now make the hash point to the new add:
A2-+
| |
(Head)---A1 x--x--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
Example 2 : we need the extra seek in each _Add()
add a node C at hash 3
A--+--+
| |
(Head)---A (E) C--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
the funny notation is to indicate that bucket 2 still
points to node E.
now add a node B at hash 2
we currently point to node (E)
the previous node is (C), which is greater than B, so
we step back; now the current is (C) and the previous is (A) :
A--+
| |
(Head)---A +->C--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
which is a good list, so we do the normal add:
A--+
| |
(Head)---A B->C--x->E--x-->(Tail)
[0] [1][2][3][4][5][6]
**************
the whole goal of this system is that the WalkNext() function is
blazing fast. The only thing that hurts in the _Add function, but
the cost of adding N nodes to hash of size M is only O(N + M*M)
(because the first M adds are O(M) and the later adds are O(1))
*****************************/
#ifdef _CRAPPY_HASH_DEBUG //{
#pragma message("using crappy debug hash implementation")
struct Hash
{
HashNode ** NodeArray;
int NodeArrayLen;
int NodeCount;
};
struct HashNode
{
ulong Key;
ulong Data;
};
Hash * Hash_Create(void)
{
Hash * H;
H = new(Hash);
assert(H);
//memset(H,0,sizeof(*H));
return H;
}
void Hash_Destroy(Hash *H)
{
assert(H);
if ( H->NodeArray )
{
int n;
for(n=0;n<H->NodeCount;n++)
{
MemPool_FreeHunk(HashNodePool_g,H->NodeArray[n]);
}
destroy(H->NodeArray);
}
destroy(H);
}
HashNode * REGCALL Hash_Add(Hash *H,ulong Key,ulong Data)
{
HashNode * hn;
hn = MemPool_GetHunk(HashNodePool_g);
assert(hn);
hn->Key = Key;
hn->Data = Data;
if ( H->NodeCount == H->NodeArrayLen )
{
H->NodeArrayLen = H->NodeCount + 100;
if ( H->NodeArray )
{
H->NodeArray = geRam_Realloc(H->NodeArray,H->NodeArrayLen*sizeof(HashNode *));
}
else
{
H->NodeArray = geRam_Allocate(H->NodeArrayLen*sizeof(HashNode *));
}
assert(H->NodeArray);
}
H->NodeArray[H->NodeCount] = hn;
H->NodeCount ++;
return hn;
}
void REGCALL Hash_DeleteNode(Hash *pHash,HashNode *pNode)
{
int n;
n = 0;
while( pHash->NodeArray[n] != pNode )
{
n++;
assert( n < pHash->NodeCount );
}
pHash->NodeArray[n] = pHash->NodeArray[ pHash->NodeCount - 1];
assert(pHash->NodeArray[n]);
pHash->NodeArray[ pHash->NodeCount - 1] = NULL;
pHash->NodeCount --;
MemPool_FreeHunk(HashNodePool_g,pNode);
}
HashNode * REGCALL Hash_Get(Hash *pHash,ulong Key,ulong *pData)
{
int n;
for(n=0;n<pHash->NodeCount;n++)
{
if ( pHash->NodeArray[n]->Key == Key )
{
if ( pData )
*pData = pHash->NodeArray[n]->Data;
return pHash->NodeArray[n];
}
}
return NULL;
}
HashNode * REGCALL Hash_WalkNext(Hash *pHash,HashNode *pCur)
{
int n;
if ( pCur )
{
n = 0;
while( pHash->NodeArray[n] != pCur )
{
n++;
assert( n < pHash->NodeCount );
}
n ++;
}
else
{
n = 0;
}
if ( n == pHash->NodeCount )
return NULL;
else
return pHash->NodeArray[n];
}
ulong REGCALL Hash_NumMembers(Hash *pHash)
{
return pHash->NodeCount;
}
#else //}{ the real thing
#define HASH_MOD (1009) // or 1013 , a nice prime
#define HASH_SIZE (HASH_MOD + 1)
#define HASH(Key) ((( ((Key)>>15) ^ (Key) )%HASH_MOD)+1)
struct Hash
{
Debug(Hash * MySelf1)
HashNode * HashTable[HASH_SIZE];
HashNode * NodeList;
Debug(int Members)
Debug(Hash * MySelf2)
};
struct HashNode
{
LinkNode LN;
ulong Key;
ulong Data;
ulong Hash;
};
Hash * Hash_Create(void)
{
Hash * pHash;
HashNode *pHead,*pTail;
pHash = new(Hash);
if ( ! pHash )
return NULL;
//memset(pHash,0,sizeof(Hash));
Debug( pHash->MySelf1 = pHash )
Debug( pHash->MySelf2 = pHash )
pTail = MemPool_GetHunk(HashNodePool_g);
assert(pTail);
LN_Null(pTail);
pTail->Key = pTail->Data = 0;
pTail->Hash = HASH_SIZE;
pHead = MemPool_GetHunk(HashNodePool_g);
assert(pHead);
LN_Null(pHead);
pHead->Key = pHead->Data = 0;
pHead->Hash = 0;
LN_AddBefore(pHead,pTail);
pHash->NodeList = pHead;
Debug(pHash->Members = 0)
return pHash;
}
void Hash_Destroy(Hash *pHash)
{
if ( pHash )
{
HashNode *pList,*pNode,*pNext;
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
Debug(pHash->Members += 2) // count Head & Tail
pList = pHash->NodeList;
LN_Walk_Editting(pNode,pList,pNext) {
MemPool_FreeHunk(HashNodePool_g,pNode);
assert(pHash->Members > 1);
Debug(pHash->Members --)
}
assert(pHash->Members == 1);
MemPool_FreeHunk(HashNodePool_g,pList);
destroy(pHash);
}
}
#ifndef NDEBUG
int Hash_ListLen(Hash *pHash,ulong H)
{
HashNode *hn;
int Len = 0;
hn = pHash->HashTable[H];
if ( ! hn )
return 0;
while( hn->Hash == H )
{
Len ++;
assert(pHash->Members >= Len);
hn = LN_Next(hn);
}
return Len;
}
#endif
HashNode * REGCALL Hash_Add(Hash *pHash,ulong Key,ulong Data)
{
ulong H;
HashNode *hn,**pTable,*Node,*Prev;
Debug( int ListLen1; int ListLen2; int HashLen1; int HashLen2; int WalkLen)
assert(pHash);
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
hn = MemPool_GetHunk(HashNodePool_g);
assert(hn);
Debug( LN_Null(hn) )
hn->Key = Key;
hn->Data = Data;
hn->Hash = H = HASH(Key);
pTable = &(pHash->HashTable[H]);
Node = *pTable;
assert( H > 0 );
assert( pHash->NodeList->Hash == 0 );
assert( ((HashNode *)LN_Prev(pHash->NodeList))->Hash == HASH_SIZE );
Debug(HashLen1 = Hash_NumMembers(pHash))
Debug(ListLen1 = Hash_ListLen(pHash,H))
if ( ! Node )
{
Prev = pHash->NodeList;
Node = LN_Next(Prev);
Debug(WalkLen = 0)
assert(Prev->Hash < H);
while( Node->Hash < H )
{
Prev = Node;
Node = LN_Next(Prev);
assert(WalkLen < pHash->Members );
Debug( WalkLen ++)
assert(Prev->Hash <= Node->Hash);
assert(Prev->Hash < HASH_SIZE );
}
assert(Prev->Hash < H);
assert(Node->Hash >= H);
}
LN_AddBefore(hn,Node);
*pTable = hn;
Debug(pHash->Members ++)
Debug(ListLen2 = Hash_ListLen(pHash,H))
assert( ListLen2 == (ListLen1 + 1) );
Debug(HashLen2 = Hash_NumMembers(pHash))
assert( HashLen2 == (HashLen1 + 1) );
return hn;
}
void REGCALL Hash_DeleteNode(Hash *pHash,HashNode *pNode)
{
HashNode ** pHead;
ulong H;
Debug( int ListLen1; int ListLen2;int HashLen1; int HashLen2)
assert(pNode );
assert( pHash );
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
assert( pNode->Hash > 0 && pNode->Hash < HASH_SIZE );
H = pNode->Hash;
pHead = & ( pHash->HashTable[H] );
Debug( HashLen1 = Hash_NumMembers(pHash) )
Debug( ListLen1 = Hash_ListLen(pHash,H) )
assert(pHash->Members > 0);
Debug(pHash->Members --)
if ( *pHead == pNode )
{
*pHead = LN_Next(pNode);
if ( (*pHead)->Hash != H )
{
// pNode was the head of the list
assert( ((HashNode *)LN_Prev(pNode))->Hash < H );
*pHead = NULL;
}
}
assert( *pHead == NULL || (*pHead)->Hash == H );
LN_Cut(pNode);
MemPool_FreeHunk(HashNodePool_g,pNode);
Debug( HashLen2 = Hash_NumMembers(pHash) )
Debug( ListLen2 = Hash_ListLen(pHash,H) )
assert( HashLen2 == (HashLen1 - 1) );
}
HashNode * REGCALL Hash_Get(Hash *pHash,ulong Key,ulong *pData)
{
ulong H;
HashNode *pNode;
assert(pHash );
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
H = HASH(Key);
assert( H > 0 && H < HASH_SIZE );
pNode = pHash->HashTable[H];
if ( ! pNode )
return NULL;
assert( pNode->Hash == H );
while( pNode->Hash == H )
{
if ( pNode->Key == Key )
{
if ( pData )
*pData = pNode->Data;
return pNode;
}
pNode = LN_Next(pNode);
}
return NULL;
}
HashNode * REGCALL Hash_WalkNext(Hash *pHash,HashNode *pNode)
{
HashNode *pNext;
assert(pHash);
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
if ( ! pNode )
{
pNode = pHash->NodeList;
assert( pNode->Hash == 0 );
}
pNext = LN_Next(pNode);
assert( pNext->Hash > 0 );
assert( pNext->Hash >= pNode->Hash );
assert( pNext != pNode );
assert( LN_Prev(pNext) == pNode );
if ( pNext->Hash == HASH_SIZE )
{
assert( ((HashNode *)LN_Next(pNext)) == pHash->NodeList );
return NULL;
}
assert(pNext->Hash < HASH_SIZE);
return pNext;
}
ulong REGCALL Hash_NumMembers(Hash *pHash)
{
ulong N;
HashNode *pNode;
assert(pHash);
assert( pHash->MySelf1 == pHash && pHash->MySelf2 == pHash );
pNode = pHash->NodeList;
assert( pNode->Hash == 0 );
pNode = LN_Next(pNode);
assert( pNode->Hash > 0 );
N = 0;
while( pNode->Hash < HASH_SIZE )
{
assert( N < (ulong)pHash->Members );
pNode = LN_Next(pNode);
N ++;
}
assert( N == (ulong)pHash->Members );
return N;
}
#endif //}{ hashes
ulong Hash_StringToKey(const char * String)
{
return crcbuf(String,strlen(String));
}
void HashNode_SetData(HashNode *pNode,ulong Data)
{
assert(pNode);
pNode->Data = Data;
}
void HashNode_GetData(HashNode *pNode,ulong *pKey,ulong *pData)
{
assert(pNode);
*pKey = pNode->Key;
*pData = pNode->Data;
}
ulong HashNode_Data(HashNode *pNode)
{
assert(pNode);
return pNode->Data;
}
ulong HashNode_Key(HashNode *pNode)
{
assert(pNode);
return pNode->Key;
}
/***************************/
bool List_Start(void)
{
assert(UsageCount >= 0 );
if ( UsageCount == 0 )
{
assert(ListPool_g == NULL && LinkPool_g == NULL);
if ( ! (ListPool_g = MemPool_Create(sizeof(List),1024,1024) ) )
return false;
if ( ! (LinkPool_g = MemPool_Create(sizeof(Link),128,128) ) )
return false;
if ( ! (HashNodePool_g = MemPool_Create(sizeof(HashNode),128,128) ) )
return false;
// could latch ListFuncs_Stop() on atexit() , but no need, really..
}
UsageCount ++;
return true;
}
bool List_Stop(void)
{
assert(UsageCount > 0 );
UsageCount --;
if ( UsageCount == 0 )
{
assert(ListPool_g && LinkPool_g );
MemPool_Destroy(ListPool_g); ListPool_g = NULL;
MemPool_Destroy(LinkPool_g); LinkPool_g = NULL;
MemPool_Destroy(HashNodePool_g); HashNodePool_g = NULL;
}
return true;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?