大师兄的数据结构学习笔记(一):线性结构

大师兄的数据结构学习笔记(二):线性结构

一、 线性表

1. 什么是线性表
  • 线性表是n个具有相同特性的数据元素的有限序列
  • 表中元素个数成为线性表的长度
  • 长度为0时,成为空表
  • 表的起始位置称表头,结束位置称表尾
2. 线性表的抽象数据类型描述
  • 类型名称:线性表(list)
  • 数据对象集: 线性表是个元素构成的有序序列(
  • 操作集:线性表,整数i表示位置,元素
  • 主要操作有:
操作 含义
SeqList() 无参数构造方法
SeqList(DataType a[], int n) 有参数构造方法
~SeqList() {} 析构函数
int Length() 获取长度
DataType Find(int i) 查找值
int Locate(DataType x) 查找位置
void Insert(int DataType x) 插入元素
DataType Delete(int i) 删除元素
void PrintList() 遍历线性表
3. 线性表存储方式
3.1 顺序存储
  • 利用数组的连续存储空间,顺序存放线性表的各元素。


  • 优点:
序号 优点
1 随机访问特性,查找O(1)时间,存储密度高。
2 逻辑上相邻的元素,物理上也相邻。
3 无须为表中元素之间的逻辑关系而增加额外的存储空间。
  • 缺点:
序号 缺点
1 插入和删除需移动大量元素。
2 当线性表长度变化较大时,难以确定存储空间的容量。
3 造成存储空间的“碎片”。
  • 代码实现:
#ifndef SEQLIST_H
#define SEQLIST_H

const int MaxSize = 100;
template 
class SeqList
{
public:
    SeqList() { length = 0; }       //无参数构造方法
    SeqList(DataType a[], int n);   //有参数构造方法
    ~SeqList() {};                  //析构函数
    int Length() { return length; } //获取长度
    DataType Find(int i);           //查找值
    int Locate(DataType x);         //查找位置
    void Insert(int i, DataType x); //插入元素
    DataType Delete(int i);         //删除元素
    void PrintList();               //遍历线性表
private:
    DataType data[MaxSize];
    int length;
};

#endif
#include "seqlist.h"
#include 

using namespace std;

template 
SeqList::SeqList(DataType a[], int n)
{
    //有参数构造方法
    if (n > MaxSize) throw "Parameter Over MaxSize";
    for (int i = 0; i < n; i++)
        data[i] = a[i];
    length = n;
}

template 
DataType SeqList::Find(int i)
{
    //按位查找
    if (i<1 && i>length) throw "Location Over Size";
    else return data[i - 1];
}

template 
int SeqList::Locate(DataType x)
{
    //按值查找
    for (int i = 0; i < length; i++)
        if (data[i] == x) return i + 1;
    return 0;
}

template 
void SeqList::Insert(int i, DataType x)
{
    //插入元素
    if (length >= MaxSize) throw "Overflow";
    if (i<1 || i>length + 1) throw "Location";
    for (int j = length + 1; j > i; j--)
        data[j] = data[j - 1];
    data[i - 1] = x;
    length++;
}

template 
DataType SeqList::Delete(int i)
{
    //删除元素
    int x;
    if (length == 0) throw "Underflow";
    if (i<1 || i>length) throw "Location";
    x = data[i - 1];
    for (int j = i; j < length; j++)
        data[j - 1] = data[j];
    length--;
    return x;
}

template 
void SeqList::PrintList()
{
    //遍历线性表
    for (int i = 0; i < length; i++)
        cout << data[i] << endl;
}
3.2 链式存储
  • 不要求逻辑上相邻的两个元素物理上也相邻。
  • 通过"链"建立起数据元素之间的逻辑关系。
  • 插入删除不需要移动数据元素,只需要修改“链”
  • 优点:
序号 优点
1 插入、删除不需移动其他元素,只需改变指针。
2 链表各个节点在内存中空间不要求连续,空间利用率高。
  • 缺点:
序号 缺点
1 查找需要遍历操作,比较麻烦。
  • 代码实现:
#ifndef SEQCHAIN_H
#define SEQCHAIN_H

template
struct Node
{
    //存储结构
    DataType data; //数据
    Node* next; //下一个节点的地址
};

template
class SeqList
{
public:
    SeqList();                      //无参数构造方法
    SeqList(DataType a[], int n);   //有参数构造方法
    ~SeqList();                 //析构函数
    int Length();                   //获取长度
    DataType Find(int i);           //查找值
    int Locate(DataType x);         //查找位置
    void Insert(int i, DataType x); //插入元素
    DataType Delete(int i);         //删除元素
    void PrintList();               //遍历线性表
private:
    Node* first;
};

#endif
#include "seqlist.h"
#include 

using namespace std;

template
SeqList::SeqList()
{
    //无参数构造方法
    first = new Node;
    first->next = nullptr;
}

template
SeqList::SeqList(DataType a[], int n)
{
    //有参数构造方法
    first = new Node;
    first->next = nullptr;
    for (int i = 0; i < n; i++)
    {
        Node* s = new Node;
        s->data = a[i];
        s->next = first->next;
        first->next = s;
    }
}

template
SeqList::~SeqList()
{
    //析构函数
    while (first != nullptr)
    {
        Node* q = first;
        first = first->next;
        delete q;
    }

}

template
int SeqList::Length()
{
    //获取长度
    Node* p = first->next;
    int count = 0;
    while(p != nullptr)
    {
        p = p->next;
        count++;
    }
    return count;
}

template
DataType SeqList::Find(int i)
{
    //查找值
    Node* p = first->next;
    int count = 1;
    while (p != nullptr && count < i)
    {
        p = p->next;
        count++;
    }
    if (p == nullptr) throw "Location";
    else return p->data;
}

template
int SeqList::Locate(DataType x)
{
    //查找位置
    Node* p = first->next;
    int count = 1;
    while (p != nullptr)
    {
        if (p->data == x) return count;
        count++;
    }
    return 0;
}

template
void SeqList::Insert(int i, DataType x)
{
    //插入元素
    Node* p = first;
    int count = 0;
    while (p != nullptr && count < i - 1)
    {
        p = p->next;
        count++;
    }
    if (p == nullptr) throw "Location";
    else {
        Node* s = new Node;
        s->data = x;
        s->next = p->next;
        p->next = s;
    }
}

template
DataType SeqList::Delete(int i)
{
    //删除元素
    Node* p = first;
    int count = 0;
    while (p != nullptr && count < i - 1)
    {
        p = p->next;
        count++;
    }
    if (p == nullptr || p->next == nullptr) throw "Location";
    else {
        Node* q = p->next;
        int x = q->data;
        p->next = q->next;
        return x;
    }
}

template
void SeqList::PrintList()
{
    //遍历线性表
    Node* p = first->next;
    while (p != nullptr)
    {
        cout << p->data << endl;
        p = p->next;
    }
}
4. 其他线性表
4.1 广义表
  • 是线性表的推广。
  • 在线性表中,元素是基本的原元素,而在广义表中,元素不仅可以是元素,也可以是另一个广义表。


  • 实现数据结构:
enum  elem_tag
{
    DATA, LIST
};

class GLnode
{
private:
    elem_tag Tag; // 0:元素节点 1:子表
    union
    {
        char data; // 元素节点的值域
        struct // 表节点
        {
            GLnode* hp;
            GLnode* tp;
        }ptr;
    };
};
4.2 多重链表
  • 链表中的节点可能同时隶属于多个链。


  • 多重链表中节点的指针域会有多个, 但包含两个指针域的链表并不一定是多重链表。
  • 经常用于树、图等复杂数据结构。
  • 以实现双链表存储方法结构为例:
template
struct Node
{
    DataType data;
    Node* prior, * next;
};

参考资料


  • https://blog.csdn.net/qq_30611601/article/details/79516986 Quanfita

本文作者:大师兄(superkmi)

你可能感兴趣的:(大师兄的数据结构学习笔记(一):线性结构)