#ifndef __GOODSTREE_H__
#define __GOODSTREE_H__
#define M 200 // 树的枝数。
#define MAX_NUM 60 // 树的深度。
typedef struct _head{
long root;
long head;
long tail;
long number;
}Head;
template <class T>
class TreeNode{
public:
int n;
long a[M+1];
T key[M];
long prev;
long next;
BOOL IsLeaf;
};
//////////////////////////////////////////////////////////////////
// CGoodsTree 是M路B+树.
template <class T>
class CGoodsTree{
public:
CGoodsTree(){ m_head.root = -1; m_IsUsed = 0;};
~CGoodsTree(){};
public:
BOOL Open(CString& FileName);
void Close();
BOOL InsertNode(T& x);
BOOL ChangeNode(T& x);
BOOL DeleteNode(T& x);
T * SearchNode(CString& pName);
T * SearchNode(long pID);
CList<T, T&> * SearchNodeList(long pType);//with h_id
CList<T, T&> * SearchNodeListEx(long pPrice);// with t_id
BOOL ChangeName(CString& pNewName, CString& pOldName);
BOOL ChangeID(long pNewID, long pOldID);
BOOL DeleteNode(CString& pName);
BOOL DeleteNode(long pID);
long GetCount();
protected:
BOOL InsertNode(long p_root, T& x);
BOOL ChangeNode(long p_root, T& x);
BOOL DeleteNode(long p_parent, long p_root, T& x, int n);
T * SearchNode(long p_root, CString& pName);
long SearchDelete();
private:
CFile m_hFile;
CList<T, T&> m_List;
T textTEMP;
Head m_head;
int m_IsUsed;
long m_newLeaf;
};
template <class T>
BOOL CGoodsTree<T>::Open(CString& FileName)
{
if(m_IsUsed++)return TRUE;
if(!m_hFile.Open(FileName, CFile::modeReadWrite))
{
m_head.root = 0;
m_head.number = 0;
m_head.head = 0;
if(!m_hFile.Open(FileName, CFile::modeCreate|CFile::modeReadWrite))
{AfxMessageBox("Cann't open the file.\n");return FALSE;}
else m_hFile.Write(&m_head,sizeof(Head));
}
else m_hFile.Read(&m_head,sizeof(Head));
return TRUE;
}
template <class T>
void CGoodsTree<T>::Close()
{
if(--m_IsUsed)return;
m_hFile.Close();
}
template <class T>
long CGoodsTree<T>::SearchDelete()
{
long p=sizeof(Head);
int q;
while(p != (long)m_hFile.GetLength())
{
m_hFile.Seek(p, CFile::begin);
m_hFile.Read(&q,sizeof(int));
if(q==0)return(p);
p+=sizeof(TreeNode<T>);
}
m_hFile.Seek(0L, CFile::end);
p=(long)m_hFile.GetPosition();
return(p);
}
template <class T>
BOOL CGoodsTree<T>::InsertNode(T& x)
{
TreeNode<T> tempNode;
m_newLeaf = 0;
InsertNode(m_head.root, x);
if(m_newLeaf != 0) //根节点分裂了。
{
tempNode.n = 1;
tempNode.a[0] = m_head.root;
tempNode.a[1] = m_newLeaf;
memcpy(&tempNode.key[0], &textTEMP, sizeof(T));
m_newLeaf = SearchDelete();
tempNode.IsLeaf = FALSE;
m_hFile.Seek(m_newLeaf, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_head.root = m_newLeaf;
m_hFile.Seek(0, CFile::begin);
m_hFile.Write(&m_head, sizeof(Head));
}
return TRUE;
}
template <class T>
BOOL CGoodsTree<T>::InsertNode(long p_root, T& x)
{
TreeNode<T> tempNode;
TreeNode<T> newNode;
long p; // 节点插入位置。
if(p_root == 0) // 新建立的文件。
{
m_hFile.Seek(p_root, CFile::end);
m_newLeaf = (long)m_hFile.GetPosition();
tempNode.n = 1;
memcpy(&tempNode.key[0], &x, sizeof(T));
tempNode.prev = tempNode.next = m_newLeaf;
tempNode.IsLeaf = TRUE;
m_head.head = m_head.tail = m_newLeaf;
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_head.root = m_newLeaf;
m_head.number = 1;
m_hFile.Seek(0, CFile::begin);
m_hFile.Write(&m_head, sizeof(Head));
m_newLeaf = 0;
}
else
{
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
if(tempNode.IsLeaf) // 在叶子节点中插入。
{
if(tempNode.n < M)
{
m_newLeaf = 0;
p = tempNode.n;
while(tempNode.key[p - 1] > x && p > 0)
memcpy(&tempNode.key[p], &tempNode.key[p - 1], sizeof(T)), p--;
tempNode.a[tempNode.n] = 0;
memcpy(&tempNode.key[p], &x, sizeof(T));
tempNode.n++;
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_head.number++;
m_hFile.Seek(0, CFile::begin);
m_hFile.Write(&m_head, sizeof(Head));
}
else
{
m_newLeaf = SearchDelete();
tempNode.n = M / 2;
newNode.n = M / 2;
memcpy(&newNode.key[0], &tempNode.key[M / 2], sizeof(T) * M / 2);
memcpy(&newNode.a[0], &tempNode.a[M / 2], sizeof(long) * (M / 2 + 1));
memcpy(&textTEMP, &newNode.key[0], sizeof(T));
newNode.next = tempNode.next;
newNode.IsLeaf = TRUE;
newNode.prev = p_root;
tempNode.next = m_newLeaf;
p = M / 2;
if(textTEMP > x)
{
while(tempNode.key[p - 1] > x && p > 0)
memcpy(&tempNode.key[p], &tempNode.key[p - 1], sizeof(T)), p--;
memcpy(&tempNode.key[p], &x, sizeof(T));
tempNode.n++;
}
else
{
while(newNode.key[p - 1] > x && p > 0)
memcpy(&newNode.key[p], &newNode.key[p - 1], sizeof(T)), p--;
memcpy(&newNode.key[p], &x, sizeof(T));
newNode.n++;
}
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_hFile.Seek(m_newLeaf, CFile::begin);
m_hFile.Write(&newNode, sizeof(TreeNode<T>));
m_head.number++;
m_hFile.Seek(0, CFile::begin);
m_hFile.Write(&m_head, sizeof(Head));
}
}
else // 在非叶子节点中插入。
{
p = tempNode.n;
while((tempNode.key[p - 1] > x) && (p > 0))p--;
InsertNode(tempNode.a[p], x);
if(m_newLeaf != 0) // 孩子节点分裂。
{
if(tempNode.n < M)
{
p = tempNode.n;
while(tempNode.key[p - 1] > x && p > 0)
{
memcpy(&tempNode.key[p], &tempNode.key[p - 1], sizeof(T));
tempNode.a[p + 1] = tempNode.a[p];
p--;
}
memcpy(&tempNode.key[p], &textTEMP, sizeof(T));
tempNode.a[p + 1] = m_newLeaf;
tempNode.n++;
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_newLeaf = 0;
}
else // 分裂非叶子节点。
{
T tempKey;
memcpy(&tempKey, &textTEMP, sizeof(T));
tempNode.n = newNode.n = M / 2;
newNode.IsLeaf = FALSE;
if(tempNode.key[M / 2 - 1] > textTEMP)
{
memcpy(&textTEMP, &tempNode.key[M / 2 - 1], sizeof(T));
memcpy(&newNode.key[0], &tempNode.key[tempNode.n], sizeof(T) * M / 2);
memcpy(&newNode.a[0], &tempNode.a[tempNode.n], sizeof(long) * (M / 2 + 1));
p = M / 2 - 1;
while(tempNode.key[p - 1] > tempKey && p >= 0)
{
memcpy(&tempNode.key[p], &tempNode.key[p - 1], sizeof(T));
tempNode.a[p + 1] = tempNode.a[p];
p--;
}
memcpy(&tempNode.key[p], &tempKey, sizeof(T));
tempNode.a[p + 1] = m_newLeaf;
}
else
{
memcpy(&newNode.key[0], &tempNode.key[tempNode.n], sizeof(T) * M / 2);
memcpy(&newNode.a[1], &tempNode.a[tempNode.n + 1], sizeof(long) * M / 2);
if(newNode.key[0] < textTEMP)
memcpy(&textTEMP, &newNode.key[0], sizeof(T));
p = 0;
while((newNode.key[p] < tempKey) && (p < newNode.n))
{
memcpy(&newNode.key[p], &newNode.key[p + 1], sizeof(T));
newNode.a[p] = newNode.a[p + 1];
p++;
}
newNode.a[p] = m_newLeaf;
if(p > 0)
memcpy(&newNode.key[p - 1], &tempKey, sizeof(T));
}
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
m_newLeaf = SearchDelete();
m_hFile.Seek(m_newLeaf, CFile::begin);
m_hFile.Write(&newNode, sizeof(TreeNode<T>));
}
}
}
}
return TRUE;
}
template <class T>
BOOL CGoodsTree<T>::ChangeNode(T& x)
{
return ChangeNode(m_head.root, x);
}
template <class T>
BOOL CGoodsTree<T>::ChangeNode(long p_root, T& x)
{
TreeNode<T> tempNode;
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
if(tempNode.IsLeaf)
{
for(int i = tempNode.n; i >=0; i--)
{
if(tempNode.key[i] == x)
{
memcpy(&tempNode.key[i], &x, sizeof(T));
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
return TRUE;
}
}
}
else
{
long p = tempNode.n - 1;
while((tempNode.key[p] > x)&&(p >= 0))
p--;
return ChangeNode(tempNode.a[p + 1], x);
}
return FALSE;
}
template <class T>
BOOL CGoodsTree<T>::ChangeName(CString& pNewName, CString& pOldName)
{
T temp, * p;
if((p = SearchNode(pOldName)) != NULL)
{
memcpy(&temp, p, sizeof(T));
DeleteNode(temp);
sprintf(temp.name, "%s", pNewName.GetBuffer(pNewName.GetLength()));
InsertNode(temp);
return TRUE;
}
else
return FALSE;
}
template <class T>
BOOL CGoodsTree<T>::ChangeID(long pNewID, long pOldID)
{
T temp, * p;
if((p = SearchNode(pOldID)) != NULL)
{
memcpy(&temp, p, sizeof(T));
DeleteNode(temp);
temp.id = pNewID;
InsertNode(temp);
return TRUE;
}
else
return FALSE;
}
template <class T>
T * CGoodsTree<T>::SearchNode(CString& pName)
{
if(m_head.root == 0)return NULL;
return SearchNode(m_head.root, pName);
}
template <class T>
T * CGoodsTree<T>::SearchNode(long p_root, CString& pName)
{
TreeNode<T> tempNode;
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
if(tempNode.IsLeaf)
{
for(int i = tempNode.n; i >=0; i--)
{
if(strcmp(tempNode.key[i].name, pName.GetBuffer(pName.GetLength())) == 0)
{
memcpy(&textTEMP, &tempNode.key[i], sizeof(T));
return &textTEMP;
}
}
}
else
{
long p = tempNode.n - 1;
while((strcmp(tempNode.key[p].name, pName.GetBuffer(pName.GetLength())) > 0)&&(p >= 0))
p--;
return SearchNode(tempNode.a[p + 1], pName);
}
return NULL;
}
template <class T>
T * CGoodsTree<T>::SearchNode(long pID)
{
if(m_head.head == 0)return NULL;
TreeNode<T> tempNode;
long p = m_head.head;
do{
m_hFile.Seek(p, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
for(long i = 0; i < tempNode.n; i++)
if(tempNode.key[i].id == pID)
{
memcpy(&textTEMP, &tempNode.key[i], sizeof(T));
return &textTEMP;
}
p = tempNode.next;
}while(p != m_head.head);
return NULL;
}
template <class T>
CList<T, T&> * CGoodsTree<T>::SearchNodeList(long pType)
// Search from B+Tree with h_id.
{
m_List.RemoveAll();
if(m_head.head == 0)return &m_List;
TreeNode<T> tempNode;
long p = m_head.head;
do{
m_hFile.Seek(p, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
for(long i = 0; i < tempNode.n; i++)
if(tempNode.key[i].h_id == pType)
m_List.AddTail(tempNode.key[i]);
p = tempNode.next;
}while(p != m_head.head);
return &m_List;
}
template <class T>
CList<T, T&> * CGoodsTree<T>::SearchNodeListEx(long pPrice)
// Search from B+Tree with t_id.
{
m_List.RemoveAll();
if(m_head.head == 0)return &m_List;
TreeNode<T> tempNode;
long p = m_head.head;
do{
m_hFile.Seek(p, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
for(long i = 0; i < tempNode.n; i++)
if(tempNode.key[i].t_id == pPrice)
m_List.AddTail(tempNode.key[i]);
p = tempNode.next;
}while(p != m_head.head);
return &m_List;
}
template <class T>
BOOL CGoodsTree<T>::DeleteNode(T& x)
{
m_newLeaf = 0;
if(m_head.root == 0)return FALSE;
DeleteNode(m_head.root, m_head.root, x, 0);
if(m_newLeaf != 0) //根节点被删除了。
{
m_head.root = m_newLeaf;
m_hFile.Seek(0, CFile::begin);
m_hFile.Write(&m_head, sizeof(Head));
}
return TRUE;
}
template <class T>
BOOL CGoodsTree<T>::DeleteNode(long p_parent, long p_root, T& x, int n)
{
TreeNode<T> tempNode, tempNode1, tempNode2;
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
long p = 0, q = 0; // q is tempNode2's point.
if(tempNode.IsLeaf)
{
if((tempNode.n > M / 2) || (p_parent == p_root))
{
while((tempNode.key[p] < x)&&(p < tempNode.n))p++;
if(tempNode.key[p] == x)
for(;p < tempNode.n; p++)
memcpy(&tempNode.key[p], &tempNode.key[p + 1], sizeof(T));
else
return FALSE;
tempNode.n--;
}
else
{ // 调整兄弟节点。
m_hFile.Seek(p_parent, CFile::begin);
m_hFile.Read(&tempNode1, sizeof(TreeNode<T>));
if(tempNode1.n > n)
{ // 与右兄弟调整。
q = tempNode1.a[n + 1];
m_hFile.Seek(q, CFile::begin);
m_hFile.Read(&tempNode2, sizeof(TreeNode<T>));
if(tempNode2.n > M / 2)
{
memcpy(&tempNode.key[tempNode.n], &tempNode2.key[0], sizeof(T));
memcpy(&tempNode1.key[n], &tempNode2.key[1], sizeof(T));
for(p = 0; p < tempNode2.n; p++)
memcpy(&tempNode2.key[p], &tempNode2.key[p + 1], sizeof(T));
tempNode2.n--;
p = 0;
while((tempNode.key[p] < x)&&(p < tempNode.n))p++;
if(tempNode.key[p] == x)
for(;p < tempNode.n + 1; p++)
memcpy(&tempNode.key[p], &tempNode.key[p + 1], sizeof(T));
else
return FALSE;
}
else
{ // 合并叶子节点。
for(p = n; p < tempNode1.n; p++)
{
memcpy(&tempNode1.key[p], &tempNode1.key[p + 1], sizeof(T));
tempNode1.a[p + 1] = tempNode1.a[p + 2];
}
tempNode1.n--;
for(p = 0; p < tempNode2.n; p++)
memcpy(&tempNode.key[tempNode.n + p], &tempNode2.key[p], sizeof(T));
tempNode.n += tempNode2.n - 1;
tempNode2.n = 0;
tempNode.next = tempNode2.next;
p = 0;
while((tempNode.key[p] < x)&&(p < tempNode.n))p++;
if(tempNode.key[p] == x)
for(;p < tempNode.n + 1; p++)
memcpy(&tempNode.key[p], &tempNode.key[p + 1], sizeof(T));
else
return FALSE;
m_newLeaf = p_root;
}
}
else
{ // 与左兄弟调整。
q = tempNode1.a[n - 1];
m_hFile.Seek(q, CFile::begin);
m_hFile.Read(&tempNode2, sizeof(TreeNode<T>));
if(tempNode2.n > M / 2)
{
memcpy(&tempNode1.key[n], &tempNode2.key[tempNode2.n - 1], sizeof(T));
tempNode2.n--;
p = tempNode.n - 1;
while((tempNode.key[p] > x)&&(p > 0))p--;
if(tempNode.key[p] == x)
for(;p >= 0; p--)
memcpy(&tempNode.key[p], &tempNode.key[p - 1], sizeof(T));
else
return FALSE;
memcpy(&tempNode.key[0], &tempNode2.key[tempNode2.n], sizeof(T));
}
else
{ // 合并叶子节点。
for(p = n; p < tempNode1.n; p++)
{
memcpy(&tempNode1.key[p], &tempNode1.key[p + 1], sizeof(T));
tempNode1.a[p + 1] = tempNode1.a[p + 2];
}
tempNode1.n--;
for(p = 0; p < tempNode.n; p++)
memcpy(&tempNode2.key[tempNode2.n + p], &tempNode.key[p], sizeof(T));
tempNode2.n += tempNode.n - 1;
tempNode.n = 0;
tempNode2.next = tempNode.next;
p = 0;
while((tempNode2.key[p] < x)&&(p < tempNode2.n))p++;
if(tempNode2.key[p] == x)
for(;p < tempNode2.n; p++)
memcpy(&tempNode2.key[p], &tempNode2.key[p + 1], sizeof(T));
else
return FALSE;
m_newLeaf = q;
}
}
m_hFile.Seek(p_parent, CFile::begin);
m_hFile.Write(&tempNode1, sizeof(TreeNode<T>));
m_hFile.Seek(q, CFile::begin);
m_hFile.Write(&tempNode2, sizeof(TreeNode<T>));
}
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
}
else
{
p = tempNode.n - 1;
while((tempNode.key[p] > x)&&(p >= 0))p--;
DeleteNode(p_root, tempNode.a[p + 1], x, p + 1);
if(m_newLeaf != 0)
{
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Read(&tempNode, sizeof(TreeNode<T>));
if(tempNode.n == 0)return TRUE;
if((tempNode.n >= M / 2)||(p_parent == p_root))
m_newLeaf = 0;
else
{
m_hFile.Seek(p_parent, CFile::begin);
m_hFile.Read(&tempNode1, sizeof(TreeNode<T>));
if(tempNode1.n > n)
{ // 与右兄弟调整。
q = tempNode1.a[n + 1];
m_hFile.Seek(q, CFile::begin);
m_hFile.Read(&tempNode2, sizeof(TreeNode<T>));
if(tempNode2.n > M / 2)
{
memcpy(&tempNode.key[tempNode.n], &tempNode1.key[n - 1], sizeof(T));
tempNode.a[tempNode.n + 1] = tempNode2.a[0];
tempNode.n++;
memcpy(&tempNode1.key[n - 1], &tempNode2.key[0], sizeof(T));
for(p = 0; p <= tempNode2.n; p++)
{
memcpy(&tempNode2.key[p], &tempNode2.key[p + 1], sizeof(T));
tempNode2.a[p] = tempNode2.a[p + 1];
}
tempNode2.n--;
m_newLeaf = 0;
}
else
{ // 合并叶子节点。
memcpy(&tempNode.key[tempNode.n], &tempNode1.key[n - 1], sizeof(T));
tempNode.n++;
for(p = n - 1; p < tempNode1.n; p++)
{
memcpy(&tempNode1.key[p], &tempNode1.key[p + 1], sizeof(T));
tempNode1.a[p + 1] = tempNode1.a[p + 2];
}
tempNode1.n--;
for(p = 0; p < tempNode2.n; p++)
{
memcpy(&tempNode.key[tempNode.n + p], &tempNode2.key[p], sizeof(T));
tempNode.a[tempNode.n + p] = tempNode2.a[p];
}
tempNode.a[tempNode.n + p] = tempNode2.a[p];
tempNode.n += tempNode2.n;
tempNode2.n = 0;
m_newLeaf = p_root;
}
}
else
{ // 与左兄弟调整。
q = tempNode1.a[n - 1];
m_hFile.Seek(q, CFile::begin);
m_hFile.Read(&tempNode2, sizeof(TreeNode<T>));
if(tempNode2.n > M / 2)
{
p = tempNode.n;
while(--p >= 0)
{
memcpy(&tempNode.key[p + 1], &tempNode.key[p], sizeof(T));
tempNode.a[p + 2] = tempNode.a[p + 1];
}
tempNode.a[1] = tempNode.a[0];
tempNode.a[0] = tempNode2.a[tempNode2.n];
memcpy(&tempNode.key[0], &tempNode1.key[n - 1], sizeof(T));
tempNode.n++;
tempNode2.n--;
memcpy(&tempNode1.key[n - 1], &tempNode2.key[tempNode2.n], sizeof(T));
m_newLeaf = 0;
}
else
{ // 合并叶子节点。
memcpy(&tempNode2.key[tempNode2.n], &tempNode1.key[n - 1], sizeof(T));
tempNode2.n++;
for(p = n; p < tempNode1.n; p++)
{
memcpy(&tempNode1.key[p], &tempNode1.key[p + 1], sizeof(T));
tempNode1.a[p + 1] = tempNode1.a[p + 2];
}
tempNode1.n--;
for(p = 0; p < tempNode.n; p++)
{
memcpy(&tempNode2.key[tempNode2.n + p], &tempNode.key[p], sizeof(T));
tempNode2.a[tempNode2.n + p] = tempNode.a[p];
}
tempNode2.a[tempNode2.n + p] = tempNode.a[p];
tempNode2.n += tempNode.n;
tempNode.n = 0;
m_newLeaf = q;
}
}
m_hFile.Seek(q, CFile::begin);
m_hFile.Write(&tempNode2, sizeof(TreeNode<T>));
m_hFile.Seek(p_parent, CFile::begin);
m_hFile.Write(&tempNode1, sizeof(TreeNode<T>));
m_hFile.Seek(p_root, CFile::begin);
m_hFile.Write(&tempNode, sizeof(TreeNode<T>));
}
}
}
return TRUE;
}
template <class T>
BOOL CGoodsTree<T>::DeleteNode(CString& pName)
{
T temp, * p;
if((p = SearchNode(pName)) != NULL)
{
memcpy(&temp, p, sizeof(T));
DeleteNode(temp);
return TRUE;
}
else
return FALSE;
}
template <class T>
BOOL CGoodsTree<T>::DeleteNode(long pID)
{
T temp, * p;
if((p = SearchNode(pID)) != NULL)
{
memcpy(&temp, p, sizeof(T));
DeleteNode(temp);
return TRUE;
}
else
return FALSE;
}
template <class T>
long CGoodsTree<T>::GetCount()
{
return m_head.number;
}
#endif