数据结构笔记二:线性表

1. 线性表的逻辑结构

线性表是由相同的数据元素组成的有限序列。
在复杂的线性表中,通常数据元素一般由数据项组成,这时一般将数据元素称为记录。
线性表可以简单的表示为:

( 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)//这里要加一
    {
        return -1;
    } 
    else
    {
        Node<elemType>* tempPtr = this->getElemPtr(position - 1);
        Node<elemType>* nextPtr = tempPtr->next;
        Node<elemType>* newPtr = new Node < elemType > ;
        newPtr->next = nextPtr;
        newPtr->data = e;
        tempPtr->next = newPtr;
        return 1;
    }
}

template<typename elemType>
SimpleLinkList<elemType>::SimpleLinkList(SimpleLinkList<elemType> &copy)
{
    if (copy.isEmpty())
    {
        this->Init();
        return;
    }
    this->Init();
    elemType e;
    Node<elemType>* tempPtr = this->head;
    for (int i = 1; i < copy.getLength(); i++)
    {
        tempPtr->next = new Node < elemType >;
        tempPtr->next->data = copy.getElem(i,e);
        tempPtr = tempPtr->next;
    }
    tempPtr->data = copy.getElem(copy.getLength(),e);
    tempPtr->next = NULL;
}

template<typename elemType>
SimpleLinkList<elemType>& SimpleLinkList<elemType>::operator=(SimpleLinkList<elemType> &copy)
{
    if (copy.isEmpty())
    {
        this->Init();
        return *this;
    }
    this->Clear();
    elemType e;
    Node<elemType>* tempPtr = this->head;
    for (int i = 1; i < copy.getLength(); i++)
    {
        tempPtr->next = new Node < elemType >;
        tempPtr->next->data = copy.getElem(i,e);
        tempPtr = tempPtr->next;
    }
    tempPtr->data = copy.getElem(copy.getLength(),e);
    tempPtr->next = NULL;

    return *this;
}
//测试文件
#include "LinkList.h"

int main(int argc, char** argv)
{
    SimpleLinkList<int> myList;
    myList.Insert(1, 1);
    myList.Insert(2, 2);
    myList.Insert(3, 3);
    myList.Insert(4, 4);
    myList.Traverse();
    cout << "链表的长度为:" << myList.getLength() << endl;
    cout << "链表是否为空:" << myList.isEmpty() << endl;

    cout << "清空链表" << endl;
    myList.Clear();
    cout << "链表是否为空:" << myList.isEmpty() << endl;
    myList.Insert(1, 1);
    myList.Insert(2, 2);
    myList.Insert(3, 3);
    myList.Insert(4, 4);

    int e;
    myList.getElem(2, e);
    cout << "第二个元素的值为:" << e << endl;

    myList.setElem(2, 8);
    myList.getElem(2, e);
    cout << "第二个元素重新设置后的值为:" << e << endl;

    myList.Delete(2, e);
    cout << "删除第二个元素后的链表为:" << endl;
    myList.Traverse();


    SimpleLinkList<int> myList2(myList);
    myList.Traverse();

    SimpleLinkList<int> myList3;
    myList3 = myList;
    myList3.Traverse();

    getchar();
    return 0;
}

线性表的链式存储结构的特点:

(1) 数据元素之间的逻辑关系由节点中的指针域表示;
(2) 每个元素的存储位置由其前驱的指针域所指示;
(3) 线性表的链式存储结构是非随机存取的存储结构;
(4) 线性表的链式存储结构中的尾节点的直接后继为空。

猜你喜欢

转载自blog.csdn.net/wuye999/article/details/79435649
今日推荐