1. 程式人生 > >資料結構筆記二:線性表

資料結構筆記二:線性表

1. 線性表的邏輯結構

線性表是由相同的資料元素組成的有限序列。
在複雜的線性表中,通常資料元素一般由資料項組成,這時一般將資料元素稱為記錄。
線性表可以簡單的表示為:

,an)" role="presentation"> ( a 1 , a 2 , , a
i , a i + 1 , , a n )

線性表中 a i 領先於 a i + 1 a i 稱為 a i + 1 的直接前驅,簡稱為前驅, a i + 1 稱為 a i 的直接後繼,簡稱為後繼。
為了更精確的定義線性表,下面給出線性表的形式定義:
LinearList = D , R
其中, D = { a i | a i D , i = 1 , 2 , 3 , , n , n 0 } , D 為某個資料集合, R = N , N = { < a i , a i + 1 > | i = 1 , 2 , , n 1 }
線性表中的資料元素個數 n 稱為線性表的長度,當 n = 0 時稱為空表。

2. 線性表包括的基本操作

1). int Lenght() const
初始條件:線性表已經存在。
操作結果:返回線性表元素的個數

2). bool Empty() const
初始條件:線性表已經存在。
操作結果:如線性表為空,則返回ture,否則返回false.

3). void Clear()
初始條件:線性表已經存在。
操作結果:清空線性表。

4). void Traverse( void (* Visit)(ElemType &) )
初始條件:線性表已經存在。
操作結果:一次對線性表的每個元素呼叫函式(* Visit)

5). void GetElem(int position, ElemType &e) const
初始條件:線性表已經存在, 1 position Length()
操作結果:用 e 返回第position位置的元素。

6). void SetElem(int position, const ElemType &e)
初始條件:線性表已經存在, 1 position Length()
操作結果:將線性表的第position位置的元素的值賦為e。

7). void Delete(int position, ElemType &e)
初始條件:線性表已經存在, 1 position Length()
操作結果:刪除線性表的第position個位置的元素,並用e返回其值,長度減1.

8). void Insert(int position, const ElemType &e)
初始條件:線性表已經存在, 1 position Length() 

3. 線性表的順序儲存結構

//.h檔案
#pragma once
#include <iostream>

using namespace std;
//首先要建立一個類,這個類中要有三個成員:元素的個數,
//順序表能儲存的最大長度,指向元素儲存空間的指標
#define DEFAULT_SIZE 10
//順序表類
template<typename elemType>
class SqList
{
private:
    //順序表實現的資料成員
    int count;      //存入元素的個數
    int maxSize;    //順序表最大能存入的元素的個數
    elemType* elem; // 指向順序表儲存空間的指標

    //輔助函式
    bool Full() const;//判斷線性表是否已經存滿
    void Init(int size);//初始化順序表

public:
    SqList(int size = DEFAULT_SIZE); //建構函式
    virtual ~SqList();//解構函式(為什麼是虛的)
    int Length() const;//求線性表長度
    bool Empty() const;//判斷線性表示否為空
    void Clear();//將線性表清空
    void Traverse();//遍歷線性表
    bool GetElem(int position, elemType &e);//獲取指定位置的元素
    bool SetElem(int position, const elemType &e);//設定指定位置的元素值
    bool Delete(int position, elemType &e);//刪除元素
    bool Insert(int position, const elemType &e);//插入元素
    int getMaxSize() const;//獲取最大順序表的容量

    SqList( SqList<elemType> &copy);//複製建構函式
    SqList<elemType> &operator=( SqList<elemType> &copy);//賦值運算子過載

};

//具體實現
template<typename elemType>
bool SqList<elemType>::Full() const
//操作結果:如果線性表已滿,則返回ture,否則返回false.
{
    return count == maxSize;
}

template<typename elemType>
void SqList<elemType>::Init(int size)
//操作結果:對線性表進行初始化
{
    maxSize = size;
    if (elem != NULL)
    {
        delete []elem;
    }   
    elem = new elemType [maxSize];
    count = 0;
}

template<typename elemType>
SqList<elemType>::SqList(int size)
//操作結果:構造大小為size的空順序表
{
    elem = NULL;
    Init(size);
}

template<typename elemType>
SqList<elemType>::~SqList()
{
    delete[]elem;
}

template<typename elemType>
int SqList<elemType>::Length() const
{
    return count;
}

template<typename elemType>
bool SqList<elemType>::Empty() const
{
    return count == 0;

}

template<typename elemType>
void SqList<elemType>::Clear()
{
    count = 0;
}

template<typename elemType>
void SqList<elemType>::Traverse()
{
    for (int curposition = 1; curposition <= count; curposition++)
    {
        cout << "第" << curposition << "個元素的值為:" << elem[curposition - 1] << endl;
    }
}

template<typename elemType>
bool SqList<elemType>::GetElem(int position, elemType &e)
{
    if (position < 1 || position > count)
    {
        return false;
    }
    else
    {
        e = elem[position - 1];
        return true;
    }
}

template<typename elemType>
bool SqList<elemType>::SetElem(int position, const elemType &e)
{
    if (position < 1 || position > count)
    {
        return false;
    }
    else
    {
        elem[position - 1] = e;
        return true;
    }
}

template<typename elemType>
bool SqList<elemType>::Delete(int position, elemType &e)
{
    if (position < 1 || position > count || Empty())
    {
        return false;
    }
    else
    {
        e = elem[position - 1];
        for (int curPosition = position; curPosition < count; curPosition++)
        {
            elem[curPosition - 1] = elem[curPosition];
        }
        count--;
        return true;
    }
}

template<typename elemType>
int SqList<elemType>::getMaxSize() const
{
    return maxSize;
}

template<typename elemType>
bool SqList<elemType>::Insert(int position, const elemType &e)
{
    if (this->count == 0)
    {
        elem[0] = e;
        count++;
        return true;
    }
    if (position < 1 || position > this->count + 1 || Full() )
    {
        return false;
    }
    else
    {
        for (int curPosition = this->count; curPosition >= position; curPosition--)
        {
            elem[curPosition] = elem[curPosition - 1];
        }
        elem[position - 1] = e;
        this->count++;
        return true;
    }
}

template<typename elemType>
SqList<elemType>::SqList( SqList<elemType> &copy)
{
    this->Init(copy.getMaxSize());
    this->count = copy.Length();
    this->maxSize = copy.getMaxSize();
    elemType e;
    for (int curPosition = 1; curPosition < this->count + 1; curPosition++)
    {
        copy.GetElem(curPosition, e);
        this->SetElem(curPosition, e);
    }
}

template<typename elemType>
SqList<elemType> & SqList<elemType>::operator=( SqList<elemType> &copy)
{

    if (&copy != this)
    {
        this->Init(copy.getMaxSize());
        this->count = copy.Length();
        this->maxSize = copy.getMaxSize();

        elemType e;
        for (int curPosition = 1; curPosition < this->count+1; curPosition++)
        {
            copy.GetElem(curPosition, e);
            this->SetElem(curPosition, e);
        }
    }
    return *this;
}

測試檔案

#include "SqList.h"

int main(int argc, char** argv)
{
    int e;
    SqList<int> myList;
    myList.Insert(1, 1);
    myList.Insert(2, 2);
    myList.Insert(3, 3);
    //myList.Traverse();
    myList.Delete(2, e);
    //myList.Traverse();
    SqList<int> myList2;
    myList2 = myList;
    myList2.Traverse();
    getchar();
    return 0;
}

線性表的順序結構儲存特點:

(1) 線性表的順序儲存結構用一組地址連續的儲存單元一次儲存線性表的元素。
(2) 順序表的物理儲存結構為:儲存在地址相鄰的儲存單元中。
(3) 線性表的順序儲存結構可以隨機的儲存任意位置的資料元素,因此線性表順序結構是一種隨機儲存的資料結構。
(4) 線性表的順序結構在進行插入和刪除時,要移動大量的資料元素。

4. 線性表的鏈式儲存結構

//.hpp檔案

#pragma once
#include <iostream>

using namespace std;
//節點類
template<typename elemType>
struct Node
{
//資料成員
    elemType data;//資料域
    Node<elemType>* next;//指標域

//建構函式
    Node();//無參建構函式
    Node(elemType item, Node<elemType>* Link = NULL);//已知資料域和指標域建立結構
};

//節點類的實現部分
template<typename elemType>
Node<elemType>::Node()
//操作結果:構造指標域為空的節點
{
    this->next = NULL;
}

template<typename elemType>
Node<elemType>::Node(elemType item, Node<elemType>* Link)
//操作結果:構造資料域為item指標域為Link的節點
{
    this->data = item;
    this->next = Link;
}


//簡單線性連結串列類
template<typename elemType>
class SimpleLinkList
{
//連結串列實現的資料成員
private:
    Node<elemType> *head; //頭節點指標

//輔助函式
    Node<elemType>* getElemPtr(int position) const;//返回指向第position個節點的指標
    void Init();//初始化線性表

public:
//抽象資料型別方法宣告以及過載編譯系統預設方法宣告
    SimpleLinkList();//無引數的建構函式
    virtual ~SimpleLinkList();//解構函式
    int getLength() const;//獲取線性表的長度
    bool isEmpty() const;//判斷線性表是否為空
    void Clear();//將線性表清空
    void Traverse();//遍歷線性表
    int getElem(int position, elemType &e) const;//獲取指定位置的元素值
    int setElem(int position, const elemType &e);//設定指定位置的元素值
    int Delete(int position, elemType &e);//刪除指定位置的值,並返回其值
    int Insert(int position, const elemType &e);//在指定位置插入值e

    SimpleLinkList(SimpleLinkList<elemType> &copy);//複製建構函式
    SimpleLinkList<elemType>& operator =(SimpleLinkList<elemType> &copy);//賦值運算子過載
};


//簡單線性連結串列實現
template<typename elemType>
Node<elemType>* SimpleLinkList<elemType>::getElemPtr(int position) const
//操作結果:獲取第position位置處的指標
{
    Node<elemType>* tempPtr = head;//用tempPtr遍歷線性連結串列以查詢第position個節點
    int curPosition = 0;//記錄tempPtr所在的連結串列的位置

    while (tempPtr != NULL && curPosition < position)
    //順指標向後查詢,直到tempPtr指向第position個節點
    {
        tempPtr = tempPtr->next;
        curPosition++;
    }

    if (tempPtr != NULL && curPosition == position)
    //查詢成功
    {
        return tempPtr;
    }
    else
    //查詢失敗
    {
        return NULL;
    }

}

template<typename elemType>
void SimpleLinkList<elemType>::Init()
{
    head = new Node < elemType > ;//構造頭指標
    head->next = NULL;
}

template<typename elemType>
SimpleLinkList<elemType>::SimpleLinkList()
{
    Init();
}

template<typename elemType>
SimpleLinkList<elemType>:: ~SimpleLinkList()
//操作結果:銷燬線性表
{
    Clear();
    delete head;
}

template<typename elemType>
int SimpleLinkList<elemType>::getLength() const
{
    int count = 0;
    for (Node<elemType> * tempPtr = head->next; tempPtr != NULL; tempPtr = tempPtr->next)
    {
        count++;
    }
    return count;
}

template<typename elemType>
bool SimpleLinkList<elemType>::isEmpty() const
{
    return head->next == NULL;
}

template<typename elemType>
void SimpleLinkList<elemType>::Clear()
//操作結果:清空線性表
{
    elemType tempele;
    while (head->next != NULL)
    {
        Delete(1, tempele);
    }
}

template<typename elemType>
void SimpleLinkList<elemType>::Traverse()
{
    int count = 1;
    for (Node<elemType> * tempPtr = head->next; tempPtr != NULL; tempPtr = tempPtr->next)
    {
        cout << "第" << count << "個元素的值為:" << tempPtr->data << endl;
        count++;
    }
}

template<typename elemType>
int SimpleLinkList<elemType>::getElem(int position, elemType &e) const
{
    Node<elemType>* tempPtr = head;
    int curPosition = 0;
    while (tempPtr->next != NULL && curPosition < position)
    {
        tempPtr = tempPtr->next;
        curPosition++;
    }

    if (curPosition == position && tempPtr != NULL)
    {
        e = tempPtr->data;
        return 1;
    }
    else
    {
        return -1;
    }
}

template<typename elemType>
int SimpleLinkList<elemType>::setElem(int position, const elemType &e)
{
    if (position < 1 || position > this->getLength())
    {
        return -1;
    }
    else
    {
        Node<elemType> * tempPtr = this->getElemPtr(position);
        tempPtr->data = e;
        return 1;
    }
}

template<typename elemType>
int SimpleLinkList<elemType>::Delete(int position, elemType &e)
{
    if (position < 1 || position > this->getLength())
    {
        return -1;
    }
    else
    {
        Node<elemType>* curPtr = this->getElemPtr(position-1);//指向刪除位置節點的前一個節點
        Node<elemType>* nextPtr = curPtr->next;
        curPtr->next = nextPtr->next;
        e = nextPtr->data;
        delete nextPtr;
        return 1;
    }
}

template<typename elemType>
int SimpleLinkList<elemType>::Insert(int position, const elemType &e)
{
    if (position < 1 || position > this->getLength() + 1)//這裡要加一