殷人昆的數據結構那本書所用的靜態鏈表無法區別鏈表尾和數組尾。所以採用這種結構。
靜態鏈表相當於是用一個數組來實現線性表的鏈式存儲結構,大概結構圖如下
在靜態鏈表中,每一個結點包含兩部分內容,一部分是data(即有意義的數據),另一部分是cur(存儲該元素下一個元素所在數組對應的下標)。
有幾個特殊的結點:
首先是下標爲0的結點中不包含有意義的數據,它的cur存儲的是備用鏈表(即沒有存儲的數據的那些結點)第一個結點的下標。如上圖2所示,數組第一個元素的cur存放的是7。
其次是數組最後一個元素,數組最後一個元素的cur存放的是靜態鏈表的第一個結點的下標(此處的第一個結點,是指有實質意義的數據的結點)。
最後就是鏈表的最後一個元素(並不一定是數組的最後一個元素),鏈表最後一個元素的cur一般存放0,表示它後面的結點爲空了。
靜態鏈表的結構:
#define MAX_SIZE = 1000 ;
typedef struct
{
ElemType data ;
int cur ;
}Component , StaticLinkList[MAX_SIZE];
靜態鏈表的初始化:
Status InitList(StaticLinkList L)
{
for(int i= 0 ; i < MAX_SIZE-1 ; ++i)
{
space[i].cur = i+1 ;
}
space[MAX_SIZE-1].cur = 0 ;
return OK ;
}
如果要插入新的結點到靜態鏈表中,首先需要得到一個備用鏈表的位置來存放新的結點,malloc_ssl就是得到一個備用鏈表的下標,並且返回。
int Malloc_SSL(StaticLinkList L )
{
int i = space[MAX_SIZE-1].cur ; //得到第一個結點的下標
if(space[0].cur) //如果存在備用鏈表
{
i = space[0].cur ; //得到備用鏈表的第一個結點的下標
}
space[0].cur = space[i].cur ; //備用結點的第一個結點將被使用,於是備用結點小標往後一個結點移動
return i ;
}
插入新結點操作:
Status InserList(StaticLinkList L , int i , ElemType e)
{
int k = MAX_SIZE-1 ;
if( i < 1 || i >Length(L)+1)
return ERROR ;
int j = Malloc_SSL(L) ; //得到備用鏈表的第一個元素
if (j) //如果元素存在
{
L[j].data = e ;
for(int m = 1 ; m < i ; ++m) //得到第i-1個元素的下標
k = L[k].cur ;
L[j].cur = L[k].cur ; //將第i-1個元素的cur設置爲新加的這個結點的下標,將新加的這個結點的下標設置爲之前第i-1個元素存儲的cur值
L[k].cur = j ;
return OK ;
}
return ERROR ;
}
刪除靜態鏈表中的元素:
Status DeleteLinkList(StaticLinkList L , int i )
{
if(i < 1 || i > ListLength(L))
return ERROR ;
int k = MAX_SIZE - 1 ;
for(int j = 1 ; j < i ; ++j) //找到第i-1個元素
{
k = L[k].cur ;
}
j = L[K].cur ; //得到第i個元素的下標
L[k].cur = L[j].cur ; //將第i個元素存儲的cur值賦值給第i-1個元素的cur
Free_SSL(L , j); //釋放掉第i個元素,第i個元素的下標爲j
return OK;
}
其中Free_SSL就是將該下標的結點放到備用鏈表中去。
void Free_SSL(StaticLinkList L , int i )
{
L[i].cur = space[0].cur ; //將之前的備用鏈表的第一個結點的小標存入到L[i]的cur中
space[0].cur = i ; //下標爲i的元素成爲備用鏈表的第一個結點
}
轉載自:http://blog.csdn.net/scu_daiwei/article/details/8511069