數據結構——靜態鏈表


      線性表的可以順序實現(數組),也可以鏈式實現(鏈表)。但是這兩種方式各有優缺點。順序實現雖然可以隨機存取數據,但是在插入或者刪除時需要移動大量元素。鏈式實現在插入或者刪除數據時只需修改其前驅、后繼的指針即可,但是在隨機存取數據時卻需要從頭開始。此時,靜態鏈表會是一個不錯的選擇。

     靜態鏈表其實就是借用一維數組來描述線性鏈表。

#define MAXSIZE 100
typedef struct{
ElemType data;
int cur;
}component,SLinkList[MAXSIZE];

  在如上述的鏈表中,結構數組的一個元素表示一個結點,同時用游標(指示器cur)代替指針指示結點在數組中的相對位置

  結構數組的第一個元素可看成是頭結點,其指針域指向的是鏈表的第一個結點。這種存儲方式仍需事先分配一個較大的空間,但是在線性表插入或者刪除數據時就不需移動數據了,只要秀高指針即可。,這就是靜態鏈表最大的優點。

 例如在靜態鏈表中實現定位函數LocateElem。

int LocateElem_SL(SLinkList S,Elemtype e){
i=S[0].cur;
while(i&&S[i].data!=e)
   i=S[i].cur;
retuen i;
}

靜態鏈表與動態鏈表的異同點

:靜態鏈表是數組實現的,是順序存儲結構,在物理地址上是連續的,而且需要預先分配大小。動態鏈表是用內存申請函數(malloc)動態申請內存的,所以每個節點的物理地址是不連續的,要通過指針來順序訪問。

:在插入或者刪除數據時只需修改指針即可,不用移動元素。

下面附一個例子:

#include <stdio.h>
#define N 100
typedef struct{
    char data;
    int cur;
}SList;
void init_sl(SList slist[]){//初始化成空閑靜態鏈表,
    int i;
    for(i=0;i<N-1;i++)
    {
        slist[i].cur=i+1;
    }
    slist[N-1].cur=0;//最后一個指針域指向0
}
int malloc_sl(SList slist[]){//分配空閑節點
    int i=slist[0].cur;//總是取頭結點之后的第一個空閑結點做分配,同時空閑鏈表非空,頭結點做調整
    if (i)
    {
        slist[0].cur=slist[i].cur;//空閑鏈表頭結點調整指針域
    }
    return i;//返回申請到的空閑節點的數組下標
}
void free_sl(SList slist[],int k){//將k節點回收
    slist[k].cur=slist[0].cur;//總是將回收的節點放在頭結點之后
    slist[0].cur=k;
}
int difference_sl(SList slist[],int n){
    int i,m,q,p;
    char tmp[2];//為避免出現scanf輸入字符出現接受回車符,則采用輸入字符串的形式
    int start,end;//start是哨兵,end指向最后的節點
    
    init_sl(slist);//初始化
    start=malloc_sl(slist);//從空閑鏈表中取出第一個空閑節點生成鏈表的頭結點
    //注意區分,現在是有一個空閑鏈表是slist,里面都是空閑節點,每次申請malloc_sl和free_sl都是操作的是slist
    //然后非空靜態鏈表,即集合A的鏈表是由start這個下標指引一直向后走,end指向非空鏈表的尾節點,
    //而且你發現start基本上都是1,因為開始的時候slist都是空閑節點,而分配又都是從頭結點slist[0]之后的第一個
    //節點,即slist[1]開始分配,所以start=1
    end=start;
    while (n--)
    {
        scanf("%s",tmp);
        i=malloc_sl(slist);
        slist[i].data=tmp[0];
        slist[end].cur=i;
        end=i;//end指針后移
    }
    slist[end].cur=0;//這個勿忘!尾節點的指針為空
    //至此A集合輸入完畢,然后處理B集合
    scanf("%d",&m);
    while (m--)
    {
        scanf("%s",tmp);
        //從A集合中掃描,如果A中存在tmp,則在A中刪除(free_sl),即A-B,如果沒有則添加入A,即B-A
        q=start;//q是p的前驅
        p=slist[start].cur;
        while (p!=slist[end].cur&&slist[p].data!=tmp[0])
        {
            q=p;
            p=slist[p].cur;
        }
        if (p!=slist[end].cur)//說明在A中找到了tmp,則刪除
        {
            slist[q].cur=slist[p].cur;//跨過p節點
            free_sl(slist,p);
            if (end==p)
            {
                end=q;//如果刪除的是尾節點,則修改尾節點指針
            }
        }else{
            i=malloc_sl(slist);
            slist[i].data=tmp[0];
            slist[i].cur=slist[end].cur;
            slist[end].cur=i;//插在end后,end位置不變,因為end是標志集合A的結束
        }
    }
    return start;
}
void print_sl(SList slist[],int start){
    int p=slist[start].cur;
    while (p)
    {
        printf("%c ",slist[p].data);
        p=slist[p].cur;
    }
    printf("\n");
}
int main(){
    int n,start;
    SList slist[N];
    freopen("1.txt","r",stdin);
    //該程序是求(A-B)U(B-A)集合運算
    while (scanf("%d",&n)==1)
    {
        start=difference_sl(slist,n);
        print_sl(slist,start);
    }
    fclose(stdin);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM