1. 程式人生 > >3.線性表的鏈式儲存結構————靜態連結串列(C語言和C++完整解析)

3.線性表的鏈式儲存結構————靜態連結串列(C語言和C++完整解析)

目錄

1.靜態連結串列的概念

因為有些語言沒有指標,所以難以實現普通連結串列,靜態連結串列就是用來解決這一問題的有力工具,靜態連結串列使用陣列來實現連結串列。靜態連結串列用遊標來代替普通連結串列的指標域,並且用下標代替普通連結串列的結點地址。

下面是一個靜態連結串列的示意圖

title=

結合上圖來分析

(1)靜態連結串列的每個結點包含三個要素:下標、資料、遊標。下標表示當前元素所處的位置,類似於連結串列的結點地址;遊標存放下一個有效結點的下標,類似於連結串列的指標域。例如下標為2的元素,存放的資料為B,遊標值為3,說明下一個結點就是C。

(2)有效結點:含有資料的結點。

(3)第一個結點和最後一個結點不存放資料。第一個結點(下標為0)存放備用連結串列的第一個結點的下標;最後一個結點相當於連結串列的頭結點,該結點的遊標存放第一個有效結點的下標,當連結串列為空的時候,遊標為0。其他結點的遊標都存放下一個結點的下標。

(4)最後一個有效結點的遊標為0,說明下一個結點為空。

2.靜態連結串列的儲存結構

使用結構體陣列型別的資料來儲存靜態連結串列:

typedef struct
{
    ElemType data;//資料
    int cur;      //遊標
}StaticLinkList[MAXSIZE];
//一維陣列型別的定義方法:定義了一個元素型別為結構體,含有MAXSIZE個元素的陣列型別StaticLinkList

3.靜態連結串列的基本操作

(1)初始化:清空靜態連結串列,建立一個空的靜態連結串列。

(2)插入結點:在指定位置插入新結點。

(3)刪除結點:刪除指定位置的結點,並且回收該節點的儲存空間以便下次再用。

(4)新建靜態連結串列:將一系列元素放入空表。

(5)獲取靜態連結串列的長度:得到靜態連結串列中有效元素的個數。

4.靜態連結串列的程式設計實現

在程式的設計思路上,靜態連結串列的新建、插入和刪除等操作跟普通連結串列差不多,只需要注意靜態連結串列的一些約定條件即可。

       4.1C語言實現靜態連結串列

(1)靜態連結串列的宣告 staticlinklist.h

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H

#define MAXSIZE 1000
typedef int ElemType;
typedef enum Bool
{
    FALSE,TRUE//列舉預設值從0開始,依次加1
}Bool;

typedef struct
{
    ElemType data;//資料
    int cur;      //遊標
}StaticLinkList[MAXSIZE];
//一維陣列型別的定義方法:定義了一個元素型別為結構體,含有MAXSIZE個元素的陣列型別StaticLinkList

Bool InitList(StaticLinkList L);//初始化靜態表(也可以用來清空靜態表)
int Malloc_SLL(StaticLinkList L);//申請新結點
Bool ListInsert(StaticLinkList L,int i,ElemType e);//指定位置插入新結點
Bool ListDelete(StaticLinkList L,int i,ElemType* e);//刪除指定位置的結點
void Free_SLL(StaticLinkList L,int k);//將已刪除的結點釋放,方便下次再用
int ListLength(StaticLinkList L);//獲取靜態表的結點數目
void display(StaticLinkList L);//顯示當前的順序表
Bool CreatList(StaticLinkList L, int n);//用隨機數新建一個靜態表,其結點個數為n

#endif // STATICLINKLIST_H

(2) 靜態連結串列的實現 staticlinklist.c

#include "staticlinklist.h"

Bool InitList(StaticLinkList L)
{
    int i;
    for(i=0;i<MAXSIZE-1;i++)
        L[i].cur=i+1;//第0個元素的遊標指向第1個有效元素的下標,有效資料是從1開始的(第一個元素不儲存資訊)

    L[MAXSIZE-1].cur=0;
    return TRUE;
}

/*獲取新節點
 *1.得到備用結點的下標
 *2.更新當前連結串列的第一個結點的遊標
 */
int Malloc_SLL(StaticLinkList L)
{
    int i=L[0].cur;//獲取備用結點的下標
    if(i)//備用連結串列不是空連結串列
        L[0].cur=L[i].cur;//更新備用連結串列頭結點
    return i;
}

//將備用連結串列的第一個結點作為待插入的新結點
//插入方法:
//1.將新結點的下標值放入待插入位置的前一個結點的遊標;
//2.新結點的遊標值為,插入正確位置後,下一個結點的下標值。
Bool ListInsert(StaticLinkList L,int i,ElemType e)
{
    int j,k,l;

    k=MAXSIZE-1;//最後一個結點存放當前連結串列的起始下標
    if(i<1||i>ListLength(L)+1)//插入位置不合理
        return FALSE;

    j=Malloc_SLL(L);//新結點下標 
    if(j)//新節點不為空
    {
        L[j].data=e;
        for(l=0;l<i-1;l++)//這個下標值對應的結點的遊標存放待插入位置的下標(包括第一個位置)
            k=L[k].cur;

        L[j].cur=L[k].cur;//新結點的遊標存放原來處於第i個位置的結點下標值(即當前結點的遊標)
        L[k].cur=j;//更新當前結點的遊標值
        return TRUE;
    }
    return FALSE;
}

Bool ListDelete(StaticLinkList L,int i,ElemType* e)
{
    int j,k;

    k=MAXSIZE-1;//待刪除的前一個結點下標
    if(i<1||i>ListLength(L))//刪除位置不合理
        return FALSE;

    for(j=0;j<i-1;j++)//尋找刪除點的下標值
        k=L[k].cur;

    j=L[k].cur;//待刪除結點的下標
    L[k].cur=L[j].cur;//待刪除結點的遊標值(下個結點的位置)賦給待刪除結點前一個結點的遊標
    *e=L[j].data;
    Free_SLL(L,j);
    return TRUE;
}

void Free_SLL(StaticLinkList L,int k)
{
    L[k].cur=L[0].cur;//待刪除結點作為新的備用連結串列頭結點,他的遊標為原來的頭結點下標
    L[0].cur=k;//更新備用連結串列頭結點的下標值
}

int ListLength(StaticLinkList L)
{
    int i=0,j;
    j=L[MAXSIZE-1].cur;//頭結點的下標值
    while (j)
    {
        i++;
        j=L[j].cur;
    }
    return i;
}

void display(StaticLinkList L)
{
    int j;
    j=L[MAXSIZE-1].cur;//頭結點的下標值
    if(j==0)
        printf("這是一個空的靜態表");
    while (j)
    {
        printf("%d  ",L[j].data);
        j=L[j].cur;
    }
    printf("\n\n");
}

Bool CreatList(StaticLinkList L, int n)//新建一個靜態表
{
    int i,j;

    if(n<1||n>MAXSIZE-2)//結點數目不合理
        return FALSE;

    if(L[MAXSIZE-1].cur)//當前靜態表非空
        return FALSE;

    j=L[0].cur;//起始結點的下標
    for(i=1;i<n;i++)
    {
        L[j].data=rand()%100;
//        printf("新建元素%d  ",L[j].data);
        j=L[j].cur;
    }

    L[j].data=rand()%100+1;//最後一個元素
    L[j].cur=0;//最後一個元素的遊標為0

    L[MAXSIZE-1].cur=L[0].cur;//最後一個結點存放當前連結串列的起始下標
    L[0].cur=j;//最後一個元素的下標
//    printf("新建元素%d  \n",L[i].data);
    return TRUE;
}

(3)測試程式 main.c

#include <stdio.h>
#include "staticlinklist.h"

int main()
{
    StaticLinkList List;
    int i;
    ElemType e;

    printf("            1.初始化靜態連結串列\n");
    InitList(List);
    display(List);

    printf("\n            2.插入5個結點\n");
    for(i=0;i<5;i++)
    {
        printf("插入第%d個結點:%d\n",i+1,i);
        ListInsert(List,i+1,i);
        display(List);
    }

    printf("\n            3.刪除5個結點\n");
    for(i=0;i<5;i++)
    {
        ListDelete(List,1,&e);
        printf("刪除第%d個結點:%d\n",i+1,e);
        display(List);
    }


//    InitList(List);新建連結串列的時候不要求連結串列必須初始化,只要是空靜態表就能新建
    printf("\n            4.隨機建立10個結點\n");
    CreatList(List,10);
    display(List);

    printf("\n            5.清空靜態表\n");
    InitList(List);
    display(List);

    return 0;
}

       4.2C++實現靜態連結串列

(1)靜態連結串列的宣告  staticlinklist.h

#ifndef STATICLINKLIST_H
#define STATICLINKLIST_H

#define MAXSIZE 1000

template<typename ElemType>//用類模板來代替typedef int ElemType;
class staticLinkList
{
public:
    staticLinkList();//初始化靜態表
    typedef struct
    {
        ElemType data;//資料
        int cur;      //遊標
    }Node;

    int Malloc_SLL();//申請新結點
    bool ListInsert(int i,ElemType e);//指定位置插入新結點
    bool ListDelete(int i,ElemType* e);//刪除指定位置的結點
    void Free_SLL(int k);//將已刪除的結點釋放,方便下次再用
    int ListLength();//獲取靜態表的結點數目
    void display();//顯示當前的順序表
    bool CreatList(ElemType a[],int n);//用隨機數新建一個靜態表,其結點個數為n
    void ListDelete();
private:
    Node L[MAXSIZE];

};

#endif // STATICLINKLIST_H

(2)靜態連結串列的實現  staticlinklist.cpp

#include <iostream>
#include "staticlinklist.h"
using namespace std;

template<typename ElemType>
staticLinkList<ElemType>::staticLinkList()
{
    int i;
    for(i=0;i<MAXSIZE-1;i++)
        L[i].cur=i+1;//第0個元素的遊標指向第1個有效元素的下標,有效資料是從1開始的(第一個元素不儲存資訊)
    L[MAXSIZE-1].cur=0;
}

template<typename ElemType>
int  staticLinkList<ElemType>::Malloc_SLL()
{
    int i=L[0].cur;//獲取備用結點的下標
    if(i)//備用連結串列不是空連結串列
        L[0].cur=L[i].cur;//更新備用連結串列頭結點
    return i;
}

template<typename ElemType>
bool staticLinkList<ElemType>::ListInsert(int i,ElemType e)
{
    int j,k,l;

    k=MAXSIZE-1;//最後一個結點存放當前連結串列的起始下標
    if(i<1||i>ListLength()+1)//插入位置不合理
        return  false;

    j=Malloc_SLL();//新結點下標
    if(j)//新節點不為空
    {
        L[j].data=e;
        for(l=0;l<i-1;l++)//這個下標值對應的結點的遊標存放待插入位置的下標(包括第一個位置)
            k=L[k].cur;

        L[j].cur=L[k].cur;//新結點的遊標存放原來處於第i個位置的結點下標值(即當前結點的遊標)
        L[k].cur=j;//更新當前結點的遊標值
        return  true;
    }
    return  false;
}

template<typename ElemType>
bool staticLinkList<ElemType>::ListDelete(int i,ElemType* e)
{
    int j,k;

    k=MAXSIZE-1;//待刪除的前一個結點下標
    if(i<1||i>ListLength())//刪除位置不合理
        return  false;

    for(j=0;j<i-1;j++)//尋找刪除點的下標值
        k=L[k].cur;

    j=L[k].cur;//待刪除結點的下標
    L[k].cur=L[j].cur;//待刪除結點的遊標值(下個結點的位置)賦給待刪除結點前一個結點的遊標
    *e=L[j].data;
    Free_SLL(j);
    return  true;
}

template<typename ElemType>
void staticLinkList<ElemType>::Free_SLL(int k)
{
    L[k].cur=L[0].cur;//待刪除結點作為新的備用連結串列頭結點,他的遊標為原來的頭結點下標
    L[0].cur=k;//更新備用連結串列頭結點的下標值
}

template<typename ElemType>
int  staticLinkList<ElemType>::ListLength()
{
    int i=0,j;
    j=L[MAXSIZE-1].cur;//頭結點的下標值
    while (j)
    {
        i++;
        j=L[j].cur;
    }
    return i;
}

template<typename ElemType>
void staticLinkList<ElemType>::display()
{
    int j;
    j=L[MAXSIZE-1].cur;//頭結點的下標值
    if(j==0)
        printf("這是一個空的靜態表");
    while (j)
    {
        cout<<L[j].data<<"  ";
        j=L[j].cur;
    }
    cout<<endl<<endl;
}

template<typename ElemType>
bool staticLinkList<ElemType>::CreatList(ElemType a[],int n)
{
    int i,j;

    if(n<1||n>MAXSIZE-2)//結點數目不合理
        return  false;

    if(L[MAXSIZE-1].cur)//當前靜態表非空
        return  false;

    j=L[0].cur;//起始結點的下標
    for(i=0;i<n-1;i++)
    {
        L[j].data=a[i];
        j=L[j].cur;
    }

    L[j].data=a[i];//最後一個元素
    L[j].cur=0;//最後一個元素的遊標為0

    L[MAXSIZE-1].cur=L[0].cur;//最後一個結點存放當前連結串列的起始下標
    L[0].cur=j;//最後一個元素的下標
    return  true;
}

template<typename ElemType>
void staticLinkList<ElemType>::ListDelete()
{
    int i;
    for(i=0;i<MAXSIZE-1;i++)
        L[i].cur=i+1;//第0個元素的遊標指向第1個有效元素的下標,有效資料是從1開始的(第一個元素不儲存資訊)
    L[MAXSIZE-1].cur=0;
}

(3)測試程式  main.cpp

#include <iostream>
#include "staticlinklist.cpp"//類模板要求在編譯的時候能同時訪問模板定義和方法定義
using namespace std;

int main()
{
    staticLinkList<int> List;//模板類
    int i,e;

    cout<<"            1.初始化靜態連結串列\n"<<endl;
    List.display();

    cout<<"\n            2.插入5個結點\n"<<endl;
    for(i=0;i<5;i++)
    {
        cout<<"插入第"<<i+1<<"個結點:"<<i<<endl;
        List.ListInsert(i+1,i);
        List.display();
    }

    cout<<"\n            3.刪除5個結點\n"<<endl;
    for(i=0;i<5;i++)
    {
        List.ListDelete(1,&e);
        cout<<"刪除第"<<i+1<<"個結點:"<<e<<endl;
        List.display();
    }

    cout<<"\n            4.新建靜態表\n"<<endl;
    int a[10];
    for(i=0;i<10;i++)
        a[i]=rand()%100;
    List.CreatList(a,10);
    List.display();

    cout<<"\n            5.清空靜態表\n"<<endl;
    List.ListDelete();
    List.display();

    return 0;
}

       4.3測試結果

5.靜態連結串列的特點

優點:

與單鏈表類似,插入和刪除的時候不需要移動大量元素;

缺點:

1.沒有解決連續儲存分配(陣列)帶來的表長難以確定的問題;

2.失去了順序儲存結構隨機存取的特性。

6.參考資料

相關推薦

3.線性儲存結構————靜態連結串列C言和C++完整解析

目錄 1.靜態連結串列的概念 因為有些語言沒有指標,所以難以實現普通連結串列,靜態連結串列就是用來解決這一問題的有力工具,靜態連結串列使用陣列來實現連結串列。靜態連結串列用遊標來代替普通連結串列的指標域,並且用下標代替普通連結串列的結點

【資料結構線性儲存(四)靜態連結串列

靜態連結串列的初始化插入刪除操作 程式碼收穫 靜態連結串列有一個備用連結串列和資料兩條鏈在一個數組空間裡。 比較特別的是需要對是否空鏈進行討論,只有在空鏈時,-1遊標對應的索引的資料是無效資料。 用scanf記得後面要把回車吃掉。 插入和刪除需要考慮備用連結串

線性——儲存結構合併操作

     採取的結構和上一篇博文一致,均為單鏈表儲存結構。#include<iostream> #include<stdio.h> #include<stdlib.h> #define ElemType int #define Status

【資料結構線性儲存(二)迴圈連結串列

線性錶鏈式儲存的迴圈單鏈表 迴圈連結串列從任意一點出發,可以訪問全部節點。 一般為了便於操作,將連結串列的頭指標變為尾指標,指向尾節點,連結串列的頭節點則為尾指標的next。 程式碼收穫 用尾指標進行操作雖然省下迴圈,但是插入刪除等操作都需要移動尾指標導致

資料結構導論-2.4 線性儲存之迴圈連結串列與雙向迴圈連結串列

迴圈連結串列與雙向迴圈連結串列 一、迴圈連結串列 1.思路 對於單鏈表而言,最後一個結點的指標域是空指標,如果將該連結串列頭指標置入該指標域,則使得連結串列頭尾結點相連,就構成了單迴圈連結串列。 2.特點 無須增加儲存量,僅對錶的連結方式稍作改變,即可使得表處理更加

3.3 棧的儲存結構

<?php header("content-type:text/html;charset=utf-8"); /** * 棧的鏈式儲存結構的基本操作 * *包括 * 1.初始化 __contruct() * 2.進棧操作 push() * 3.出棧操作 pop() * 4.銷燬棧 de

大話資料結構 —— 3.6 線性儲存結構

3.6.1 順序儲存結構不足的解決辦法 C同學:反正要在相鄰元素間留多少空間都是有可能不夠的,那不如乾脆不要考慮相鄰位置這個問題了。哪裡有空位就放在哪裡,此時指標剛好可以派上用場。 每個元素多用一個

2.3 線性儲存結構(連結串列)

基本概念和特點 連結串列的定義 -線性表的鏈式儲存結構稱之為連結串列(linked list)。連結串列包括兩部分構成:資料域和指標域。資料域儲存資料元素,指標域描述資料元素的邏輯關係。 - 連結串列通常使用帶頭結點的表示。指向頭結點的指標稱之為頭指標

走進資料結構和演算法c++版3——線性儲存結構

線性表的鏈式儲存結構   我們知道線性表的順序儲存結構在插入和刪除操作時需要移動大量的資料,他們的時間複雜度為O(n)O(n)。當我們需要經常插入和刪除資料時,順序儲存結構就不適用了,這時我們就需要用到線性表的鏈式儲存結構。   線性表的鏈式儲存結構的特點是

資料結構 筆記:線性儲存結構

鏈式儲存的定義 為了表示每個資料元素與其直接後繼元素之間的邏輯關係;資料元素出了儲存本身的資訊外,還需要儲存直接後繼的資訊。 ps:在邏輯上,元素之間是相鄰的;在實體記憶體中元素之間並無相鄰關係。 鏈式儲存邏輯結構 -基礎鏈式儲存結構的線性表中,每個節點都包含資料域和指標域 ·資

資料結構線性儲存結構單鏈(C++)

一. 標頭檔案—linkedlist.h 1 #ifndef _LIKEDLIST_H_ 2 #define _LIKEDLIST_H_ 3 4 #include <iostream> 5 6 template <class T> 7 struc

線性儲存結構的基本操作(經編譯)

/* 連結串列銷燬的時候,是先銷燬了連結串列的頭,然後接著一個一個的把後面的結點銷燬了,這樣這個連結串列就不能再使用了。 連結串列清空的時候,是先保留了連結串列的頭,然後把頭後面的所有的結點都銷燬,最後把頭裡指向下一個的指標設為空,這樣就相當與清空了,但這個連結

【資料結構線性儲存結構--單鏈

1. 線性表的鏈式儲存結構 鏈式儲存:用一組任意的儲存單元儲存線性表中的資料元素。用這種方法儲存的線性表簡稱線性連結串列。 儲存連結串列中結點的一組任意的儲存單元可以是連續的,也可以是不連續的,甚至是零散分佈在記憶體中的任意位置上的。 連結串列中結點的邏輯順序和物理順序不

線性包括順序儲存結構儲存結構

還記得資料結構這個經典的分類圖吧: 今天主要關注一下線性表。 什麼是線性表 線性表的劃分是從資料的邏輯結構上進行的。線性指的是在資料的邏輯結構上是線性的。即在資料元素的非空有限集中 (1) 存在唯一的一個被稱作“第一個”的資料元素,(2) 存在唯一的一個被稱

線性儲存結構

2.3.1 線性表的鏈式儲存結構——連結串列 連結串列: 1.每個節點中除資料域外,設定了一個指標域,用以指向其後繼節點,這樣構成的連結表稱為線性單向連結串列,簡稱單鏈表。 2.每個節點中除資料域外,設定兩個指標域,分別用以指向其前驅節點和

2.線性儲存結構————單鏈思路分析,C語言、C++完整程式

目錄 1.單鏈表的基本概念 (1)單鏈表:當連結串列中的每個結點只含有一個指標域時,稱為單鏈表。 (2)頭指標:如上圖所示,連結串列中第一個結點的儲存位置叫做頭指標。 (3)頭結點:頭結點是放在第一個元素結點之前的結點,頭結點不是連結串列中的必

線性儲存結構從建插入到 刪除銷燬

檔案1    list.c#include<stdio.h> #include"list.h" #include<stdlib.h> #include<string.h> /* 函式名 creatList; 功能 建立連結串列 申請空間

線性儲存結構

鏈式儲存定義: 為了表示每個資料元素與其直接後繼元素之間的邏輯關係,每個元素除了儲存本身的資訊外,還需要儲存指示其直接後繼的資訊。 單鏈表包括: 表頭結點:連結串列中的第一個結點,包含指向第一個資料元素的指標以及連結串列自身的一些資訊。 資料結點:連結串列中代表資料元素的

C語言實現線性儲存結構

線性表的鏈式儲存結構 特點 結點除自身的資訊域外,還有表示關聯資訊的指標域。因此,鏈式儲存結構的儲存密度小、儲存空間利用率低。 在邏輯上相鄰的結點在物理上不必相鄰,因此,不可以隨機存取,只能順序存取。 插入和刪除操作方便靈活,不必移動結點只需修改結點

線性、棧、佇列的儲存結構

一、順序儲存結構與鏈式儲存結構的區別        順序儲存就是從記憶體中取出一段連續地址的空間,將資料依次連續的儲存在這段空間中。而鏈式儲存結構是指資料儲存在記憶體中的地址是離散的,以資料節點為單