Orthogonal-List 十字链表(更新时间:2016-04-15)
在课上边听着哈希表,便看着科比告别直播,边写这个十字链表,23333,感觉好充实。
果然,在看完科比最后一场比赛神奇的演出之后,当天就不想好好学习了,就拖了一天。
十字链表
十字链表是一维链表的扩展,通过将以一个指针域扩展到两个指针域使得链表能够以二维的形式串联起来,我们可以形象的使用二维数组来描述十字链表(实际实现效果基本与二维数组无异)。
在定义结构的时候,Doge使用了union
来复合使用Data
域从而使得我们不需要重新定义新的行列头节点。
对于Insert()
以及Find()
这类的函数实现的时候所需要用到的遍历操作,Doge均采用先访问行,在访问列的方式直接去查找。
另外Delete()
的实现与Insert()
的实现基本没有差异,只是在搜索的时候返回的是前驱结点然后将其从十字链表中移除即可,Doge在这里就不给出了,留待读者自行编写。
十字链表的删除实质上等价于先将每一行(或者每一列,二选一即可)的链表进行删除,再将行列头数组删除即可,均使用free()
函数来释放空间。
十字链表最经典的应用就是用于计算稀疏矩阵,之后Doge会将自己做的矩阵运算整理后上传。
下面直接给出代码示例:
struct Node;
typedef struct Node *PtrToNode;
typedef PtrToNode OList; //十字链表头指针定义
typedef PtrToNode OLNode; //十字链表节点定义
typedef int ElementType; //十字链表数据类型定义
struct Node
{
int Row; //行号
int Col; //列号
OLNode Down; //纵向链接
OLNode Right; //横向链接
union Data //数值域
{
ElementType Element; //矩阵数值
OLNode Next; //行列头指针链表
} Data;
};
OList CreatOList( int Row, int Col )
{
OList OL;
OLNode OLN[LMAX+1];
int cap;
OL = ( OLNode ) malloc ( sizeof( struct Node ) ); //十字链表头结点的建立
OL->Row = Row; //十字链表行号确定
OL->Col = Col; //十字链表列号确定
OLN[0] = OL; //十字链表头节点
cap = Max( Row, Col ); //十字链表容量确定
for( int ri = 1; ri <= cap; ri ++ ) //十字链表行列头的初始化
{
OLN[ri] = Initial();
OLN[ri-1]->Data.Next = OLN[ri]; //十字链表行列头的串联
}
OLN[cap]->Data.Next = OL;
return OL;
}
OLNode Initial( void ) //十字链表节点初始化
{
OLNode tmp;
tmp = ( OLNode ) malloc ( sizeof( struct Node ) ); //分配节点空间
tmp->Row = tmp->Col = 0; //行列初始化
tmp->Right = tmp->Down = tmp; //节点自链接
return tmp;
}
ElementType Find( OList L, int Row, int Col ) //十字链表元素的定点查找
{
int ri;
OLNode LL = L->Data.Next; //游标初始化
for( ri = 1; ri < Row; ri++ ) //寻找行头节点
LL = LL->Data.Next;
while( LL->Col < Col && LL->Right->Col != 0 ) //确定列号
LL = LL->Right;
if( LL->Col == Col )
return LL->Data.Element;
else
return 0;
}
OLNode Find( OList L, ElementType X ) //十字链表元素的查找
{
OLNode LL = L->Data.Next;
for( int ri = 1; ri < L->Row; ri++ ) //行循环
{
while( LL->Right->Col != 0 && LL->Data.Element != X ) //列循环
LL = LL->Right;
if( LL->Data.Element = X )
return LL;
else
LL = LL->Right->Data.Next;
}
}
OList Insert( OList L, int Row, int Col, ElementType X ) //十字链表的定点元素插入
{
OLNode LL;
OLNode tmp;
tmp = Initial();
tmp->Data.Element = X;
tmp->Row = Row;
tmp->Col = Col;
//行插入
LL = L->Data.Next;
for( int ri = 1; ri < Row; ri++ )
LL = LL->Data.Next;
while( LL->Right->Col < Col && LL->Right->Col != 0 )
LL = LL->Right;
tmp->Right = LL->Right; //插入
LL->Right = tmp;
//列插入
LL = L->Data.Next;
for( int ri = 1; ri < Col; ri++ )
LL = LL->Data.Next;
while( LL->Down->Row < Row && LL->Down->Row != 0 )
LL = LL->Down;
tmp->Down = LL->Down; //插入
LL->Down = tmp;
return L;
}
int Max( int m, int n ) //辅助函数,选取较大值
{
if( m > n )
return m;
else
return n;
}