重新复习数据结构,十字链表主要在两个地方应用:稀疏矩阵的存储, 有向图的存储。
稀疏矩阵,常用三元组存储,但是当矩阵的非零元素和位置在操作过程中变化较大时,就不一采用顺序结构存储了,此时十字链表就是不错的选择。
下面是十字链表的数据结构,以及创建函数,篇幅有限没有帖内存释放的函数:
typedef
struct
QLNode
... {
int iPos, jPos; //非零元素的行列下标;
int iElem; //元素;
struct QLNode *right, *down;
} QLNode;
typedef struct QLNode * QLink;
typedef struct
... {
QLink *rHead, *cHead; //行列的头指针;
int RowNum, ColNum, TotalNum;
} CrossList;
bool CreatCrossList(CrossList & CroLit)
... {
int row, coll, total;
cin>>row>>coll>>total;
CroLit.RowNum=row; CroLit.ColNum=coll; CroLit.TotalNum=total;
CroLit.rHead= new QLink[row]; //创建行头指针表;
CroLit.cHead= new QLink[coll]; //创建列头指针表;
//初始化头指针表;
for (int i=0; i<row; i++)
CroLit.rHead[i]=NULL;
for (int i=0; i<coll; i++)
CroLit.cHead[i]=NULL;
int i, j, elem; //以三元组的形式输入
for(cin>>i>>j>>elem; elem!=0; cin>>i>>j>>elem)
...{
QLink pTem= new QLNode;
pTem->right=pTem->down=NULL;
pTem->iPos=i; pTem->jPos=j; pTem->iElem=elem;
//直接插入:空,或者列坐标大于此行链表中的最大列坐标
// 同一行里面,链表按照列的坐标排序,
if( CroLit.rHead[i]==NULL || CroLit.rHead[i]->jPos>j )
...{
pTem->right= CroLit.rHead[i];
CroLit.rHead[i]=pTem;
}
else //查寻在行表中的插入位置:
...{
QLink bg;
for(bg=CroLit.rHead[i]; bg->right && bg->right->jPos<j; bg=bg->right);
pTem->right=bg->right; bg->right=pTem;
} //完成行插入。
//直接插入:空,或者行坐标大于此列链表中的最大行坐标
// 同一列里面,链表按照行的坐标排序,
if( CroLit.cHead[j]==NULL || CroLit.cHead[j]->iPos>i )
...{
pTem->down= CroLit.cHead[j];
CroLit.cHead[j]=pTem;
}
else //查寻在列表中的插入位置:
...{
QLink bg;
for(bg=CroLit.cHead[j]; bg->down && bg->down->iPos<i; bg=bg->down);
pTem->down=bg->down; bg->down=pTem;
} //完成列插入。
}
return true;
}
// 输出各行元素
void DisplayRow(CrossList dest)
... {
for (int i=0; i<dest.RowNum; i++)
...{
QLink tem=dest.rHead[i];
while (tem)
...{
cout<<"( "<<tem->iPos<<", ";
cout<<tem->jPos<<", ";
cout<<tem->iElem<<" )";
tem=tem->right;
}
cout<<endl;
}
}
... {
int iPos, jPos; //非零元素的行列下标;
int iElem; //元素;
struct QLNode *right, *down;
} QLNode;
typedef struct QLNode * QLink;
typedef struct
... {
QLink *rHead, *cHead; //行列的头指针;
int RowNum, ColNum, TotalNum;
} CrossList;
bool CreatCrossList(CrossList & CroLit)
... {
int row, coll, total;
cin>>row>>coll>>total;
CroLit.RowNum=row; CroLit.ColNum=coll; CroLit.TotalNum=total;
CroLit.rHead= new QLink[row]; //创建行头指针表;
CroLit.cHead= new QLink[coll]; //创建列头指针表;
//初始化头指针表;
for (int i=0; i<row; i++)
CroLit.rHead[i]=NULL;
for (int i=0; i<coll; i++)
CroLit.cHead[i]=NULL;
int i, j, elem; //以三元组的形式输入
for(cin>>i>>j>>elem; elem!=0; cin>>i>>j>>elem)
...{
QLink pTem= new QLNode;
pTem->right=pTem->down=NULL;
pTem->iPos=i; pTem->jPos=j; pTem->iElem=elem;
//直接插入:空,或者列坐标大于此行链表中的最大列坐标
// 同一行里面,链表按照列的坐标排序,
if( CroLit.rHead[i]==NULL || CroLit.rHead[i]->jPos>j )
...{
pTem->right= CroLit.rHead[i];
CroLit.rHead[i]=pTem;
}
else //查寻在行表中的插入位置:
...{
QLink bg;
for(bg=CroLit.rHead[i]; bg->right && bg->right->jPos<j; bg=bg->right);
pTem->right=bg->right; bg->right=pTem;
} //完成行插入。
//直接插入:空,或者行坐标大于此列链表中的最大行坐标
// 同一列里面,链表按照行的坐标排序,
if( CroLit.cHead[j]==NULL || CroLit.cHead[j]->iPos>i )
...{
pTem->down= CroLit.cHead[j];
CroLit.cHead[j]=pTem;
}
else //查寻在列表中的插入位置:
...{
QLink bg;
for(bg=CroLit.cHead[j]; bg->down && bg->down->iPos<i; bg=bg->down);
pTem->down=bg->down; bg->down=pTem;
} //完成列插入。
}
return true;
}
// 输出各行元素
void DisplayRow(CrossList dest)
... {
for (int i=0; i<dest.RowNum; i++)
...{
QLink tem=dest.rHead[i];
while (tem)
...{
cout<<"( "<<tem->iPos<<", ";
cout<<tem->jPos<<", ";
cout<<tem->iElem<<" )";
tem=tem->right;
}
cout<<endl;
}
}
举个例子,稀疏矩阵:
| 3 0 0 5 |
| 0 2 0 0 |
| 2 0 0 0 |
/*测试输入:
3 4 4
0 0 3
0 3 5
1 1 2
2 0 2
0 0 0 /表示结束*/
/*测试输出:
( 0, 0, 3 )( 0, 3, 5 )
( 1, 1, 2 )
( 2, 0, 2 )
请按任意键继续. . .*/
下面是该十字链表的存储图: