C#實現數據結構——線性表(上)


什么是線性表

數據結構中最常用也最簡單的應該就是線性表,它是一種線性結構(廢話,不是線性結構怎么會叫線性表?當然不是廢話,古人公孫龍就說白馬非馬,現代生物學家也說鯨魚不是魚)。

那什么是線性結構?

按數據邏輯結構來划分,數據結構就分為線性結構和非線性結構。
通俗來說就是排成一條線的結構,想象一下你去食堂排隊打飯,前面站着一個人,后面也站着一個人,這樣的結構就是線性結構。

線性表的定義

線性表就是線性結構的一種(其實其它像棧、隊列什么的也可以說是一種特殊的線性表),先看一下線性表的定義:
零個或多個數據元素的有限序列。
零個或多個意味着線性表的數據元素n大於等於0,當n=0時,也就是空表。
有限意味着這個表的數據有限的,計算機中處理的數據都是有限的。
序列也就是說這一組元素是有順序的,如果沒有順序亂成一團就不是排隊而是打架了。


你去食堂打飯,發現來的時間點不對,一個人都沒有,這時就是一張空表。於是你在外面轉了一圈,回來一看,媽呀,一根煙的時間打飯窗口就站了幾十號人,於是你趕快排在最后面,剛站好,你后面又一下站了十幾個人。
這時,排在一個的就是第一個元素,排在最后一個的就是最后一個元素,排在你前面的就叫前驅,排你后面叫后繼。而排在第一個的人前面已經沒人了,所以第一個元素無前驅。同理,排在最后的一個無后繼。
你排在中間實在太無聊了,於是數了一下,隊伍總共100個人,也就是說線性表當前的長度為100。你又算了一下,從打飯窗口到門口可以排150個人,也就是說理論上隊伍最多只能排150個人,150就是線性表的最大存儲容量。如果還有人要排進來就要站到門外面了,就會發生數據溢出。

接口定義

后面我們將要介紹到多種實現線性表的方式,但不管哪種方式實現的線性表都是一樣的,里面定義方法也是一樣的。使用接口可以確保每種方式都實現了相同的操作,方便程序解耦,更利於其它模塊調用以及編寫單元測試。
下面給出定義的接口:

public interface ILinearList<T>
{
    /// <summary>
    /// 數組長度
    /// </summary>
    int Length
    {
        get;
    }

    /// <summary>
    /// 數組是否為空
    /// </summary>
    /// <returns></returns>
    bool IsEmpty();

    /// <summary>
    ///清空表 
    /// </summary>
    void Clear();

    /// <summary>
    ///通過索引獲取數據元素 
    /// </summary>
    /// <param name="index"></param>
    /// <returns></returns>
    T GetItem(int index);

    /// <summary>
    /// 返回數據元素的索引
    /// </summary>
    /// <param name="t"></param>
    /// <returns></returns>
    int LocateItem(T t);

    /// <summary>
    /// 將數據元素插入到指定位置
    /// </summary>
    /// <param name="item"></param>
    /// <param name="index"></param>
    void Insert(T item, int index);

    /// <summary>
    /// 在數組末尾添加元素
    /// </summary>
    /// <param name="item"></param>
    void Add(T item);

    /// <summary>
    /// 刪除指定索引的元素
    /// </summary>
    /// <param name="index"></param>
    void Delete(int index);
}

線性表順序存儲結構

線性表有兩種物理結構——順序存儲結構和鏈式存儲結構。我們先來看看順序存儲結構。
順序存儲結構就和前面的排隊一樣,設計一個排隊窗口,定下最多可以排多少人,然后按順序一個個這么排下去。也就是說在內存中分配一塊內存空間,然后把相同數據類型的數據元素依次存放下去。

如何實現

使用一維數組,把第一個數據元素存到數組下標為0的位置中,接着把線性表相鄰的元素存儲在數組中相鄰的位置。
用C#實現,可以直接使用泛型數組。

初始化

首先我們先定義一些屬性及字段:

    private T[] list;

    private int length = 0;

    public int MaxSize
    {
        private set;
        get;
    }

    public int Length
    {
        get { return length; }
    }

構建線性表只需要給定數組最大容量(MaxSize)然后將list集合初始化就行了,這些我們可以直接放在構造函數里面:

    public SequentialList(int maxSize)
    {
        if (maxSize <= 0)
        {
            throw new Exception("the maxSize can not be less than zero");
        }
        MaxSize = maxSize;
        list = new T[maxSize];
    }

元素獲取

元素的獲取非常簡單,直接通過下標返回就可以了:

    public T GetItem(int index)
    {
        return list[index];
    }

添加元素

添加元素直接將數據元素放在數組的末尾(排隊時新來一個人直接站在最后就好),並將length加1就行了:

    public void Add(T item)
    {
        if (isFull())   //判斷數組是否已滿
        {
            throw new Exception("This linear list is full");
        }
        length++;
        list[length - 1] = item;
    }

將元素插入至指定位置

打飯時,每新來一個人就直接排到隊伍的最后面。但是現實卻總是不那么美好,總有一些人會來插隊。今天你去食堂去晚了,一看隊伍已經站了差不多一百個人,所以機智的你看了下隊伍的前列,在前面發現了坐在你邊上的美女同事,於是趕快和她打個招呼以極其自然的方式插到了她的前面。你的插入對排在美女同事前面的人來說沒有任何影響,他們的位置保持不變,但是排在她后面就要相應的全部向后移一個位置:

    public void Insert(T item, int index)
    {
        if (isFull())
        {
            throw new Exception("This linear list is full");
        }
        if (index < 0 || index > length)
        {
            throw new Exception("Location exception");
        }
        length++;
        for (int i = length - 1; i > index; i--)
        {
            list[i] = list[i - 1];
        }
        list[index] = item;
    }

刪除

你正在排隊打飯,突然發現肚子疼,心想總不能等下一邊吃進去一邊拉出來吧,於是趕快從隊伍里退出來奔向洗手間,這個時候,排在你后面的人自然是滿臉歡笑地目送你離開,他們所有人都可以往前面移一個位置:

    public void Delete(int index)
    {
        if (index < 0 || index > length - 1)
        {
            throw new Exception("Location exception");
        }
        length--;
        for (int i = index; i < length; i++)
        {
            list[i] = list[i + 1];
        }
    }

完整代碼如下(代碼爛,輕拍):

/// <summary>
/// 線性表順序結構
/// </summary>
public class SequentialList<T> : ILinearList<T>
{
    private T[] list;

    private int length = 0;

    public int MaxSize
    {
        private set;
        get;
    }

    public int Length
    {
        get { return length; }
    }

    public SequentialList(int maxSize)
    {
        if (maxSize <= 0)
        {
            throw new Exception("the maxSize can not be less than zero");
        }
        MaxSize = maxSize;
        list = new T[maxSize];
    }

    public bool IsEmpty()
    {
        return length == 0;
    }

    public void Clear()
    {
        length = 0;
    }

    public T GetItem(int index)
    {
        return list[index];
    }

    public int LocateItem(T t)
    {
        for (int i = 0; i < list.Length; i++)
        {
            if (list[i].Equals(t))
            {
                return i;
            }
        }
        return -1;
    }

    public void Insert(T item, int index)
    {
        if (isFull())
        {
            throw new Exception("This linear list is full");
        }
        if (index < 0 || index > length)
        {
            throw new Exception("Location exception");
        }
        length++;
        for (int i = length - 1; i > index; i--)
        {
            list[i] = list[i - 1];
        }
        list[index] = item;
    }

    public void Add(T item)
    {
        if (isFull())
        {
            throw new Exception("This linear list is full");
        }
        length++;
        list[length - 1] = item;
    }

    public void Delete(int index)
    {
        if (index < 0 || index > length - 1)
        {
            throw new Exception("Location exception");
        }
        length--;
        for (int i = index; i < length; i++)
        {
            list[i] = list[i + 1];
        }
    }

    bool isFull()
    {
        return length >= MaxSize;
    }
}


免責聲明!

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



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