LongDz's Digital Literary Proposals

重温数据结构-线性表

5 min

1.线性表

特点:相同类型元素、有限集合

1.1顺序表

template <class T, int N>
class SeqList
{
public:
    SeqList() { length = 0 };
    SeqList(T a[], int n);
    int GetLength() { return length; }
    void PrintList();
    void Insert(int i, T x);
    T Delete(int i);
    T Get(int i);
    int Locate(T x);

private:
    T data[N];
    int length;
};
template <class T, int N>
SeqList<T, N>::SeqList(T a[], int n)
{
    if (n > N)
        throw("数组长度超过最大限制");
    for (int i = 0; i < n; i++)
        data[i] = a[i];
    length = n;
template <class T, int N>
class SeqList
{
public:
    SeqList() { length = 0 };
    SeqList(T a[], int n);
    int GetLength() { return length; }
    void PrintList();
    void Insert(int i, T x);
    T Delete(int i);
    T Get(int i);
    int Locate(T x);

private:
    T data[N];
    int length;
};
template <class T, int N>
SeqList<T, N>::SeqList(T a[], int n)
{
    if (n > N)
        throw("数组长度超过最大限制");
    for (int i = 0; i < n; i++)
        data[i] = a[i];
    length = n;
}
template <class T, int N>
void SeqList<T, N>::PrintList()
{
    for (int i = 0; i < length; i++)
        cout << data[i] << " ";
    cout << endl;
}
template <class T, int N>
void SeqList<T, N>::Insert(int i, T x)
{
    if (n + 1 > N)
        throw("超出最大长度");
    if (i < 1 || i >= length)
        throw("位置异常");
    for (int j = length; j >= i; j--)
    {
        data[j] = data[j - 1];
    }
    data[i] = x;
    length++;
}
template <class T, int N>
T SeqList<T, N>::Delete(int i)
{
    if (i < 1 || i > length)
        throw("位置异常");
    if (length == 0)
        throw("溢出");
    T x = data[i];
    for (int j = i; j < length; j++)
    {
        data[j] = data[j + 1];
    }
    length--;
    return x;
}
template <class T, int N>
T SeqList<T, N>::Get(int i)
{
    if (i < 1 || i > length)
        throw("位置异常");
    return data[i - 1];
}
template <class T, int N>
int SeqList<T, N>::Locate(T x)
{
    int ans = 0;
    for (int i = 0; i < length; i++)
    {
        if (data[i] == x) // 注意除了基本数据类型外,需要对==进行重载
        {
            ans = i + 1;
            break;

    }
    return ans;
}

单链表

#include<iostream>
using namespace std;

template <class T>
struct Node
{
    T data;
    struct Node <T> *next;
};
template <class T>
class LinkList
{
    public:
        LinkList(){front = new Node<T>;front -> next = NULL;}
        LinkList(T a[],int n);
        ~LinkList();
        void PrintList();
        int GetLength();
        Node<T> *Get(int i);
        T Delete(int i);
        void Insert(int i,T x);
        void Insert1(int i, T x);
        int Locate(T x);
    private:
        Node<T> *front;
#include<iostream>
using namespace std;

template <class T>
struct Node
{
    T data;
    struct Node <T> *next;
};
template <class T>
class LinkList
{
    public:
        LinkList(){front = new Node<T>;front -> next = NULL;}
        LinkList(T a[],int n);
        ~LinkList();
        void PrintList();
        int GetLength();
        Node<T> *Get(int i);
        T Delete(int i);
        void Insert(int i,T x);
        void Insert1(int i, T x);
        int Locate(T x);
    private:
        Node<T> *front;
};

//带头结点的头插法
template<class T>
LinkList<T>::LinkList(T a[],int n){
    Node<T> *front = new Node<T>;
    front->next = NULL;
    for(int i = n-1;i >= 0;i--){
        Node<T> *tmp = new Node<T>;
        tmp->data = a[i];
        tmp->next = front->next;
        front->next = tmp;
    }
}
//不带头结点的头插法
template<class T>
LinkList<T>::LinkList(T a[],int n){
    if(n == 0)
    return NULL;
    else
    Node<T> *front = new Node<T>;
    front->data = a[n-1];
    for(int i = n-2;i >= 0;i--){
        Node<T> *tmp = new Node<T>;
        tmp->next = front;
        tmp->data = a[i];
        front = tmp;
    }
}
//尾插法
template <class T>
LinkList<T>::LinkList(T a[], int n)
{
    Node<T>* front = new Node<T>;
    front->next = nullptr;
    Node<T>* now = front;
    for(int i = 0;i < n;i++){
        Node<T> *p = new Node<T>;
        p -> data = a[i];
        now->next = p;
        now = p;
    }
    now->next = NULL;//注意
}

template<class T>
LinkList<T>::~LinkList(){
    Node<T>* p = front;
    while(p){
        front = p;
        p = p -> next;
        delete front;
    }
}

template<class T>
int LinkList<T>::GetLength(){
    Node<T> *p = front->next;
    int len = 1;
    while(p){
        len++;
        p = p->next;
    }
    return len;
}

template<class T>
void LinkList<T>::PrintList(){
    Node<T> *p = front->next;
    while(p){
        cout<<p->data<<" ";
        p = p->next;
    }
    cout<<endl;
}
template<class T>
Node<T> * LinkList<T>::Get(int i){
    if(i < 1)throw"位置异常";

    Node<T>*p = front -> next;
    while(i > 1){
        i--;
        if(p){
            p = p->next;
        }
        else throw"溢出";
    }
    return p;
}
//优化后的
template <class T>
Node<T> *LinkList<T>::Get(int i)
{
    if (i < 1)
        throw "位置异常";
    Node<T> *p = front->next; // 第1个数据结点
    if (!p)
        throw "溢出"; // 空表没有第1个节点
    for (int k = 1; k < i; ++k)
    {
        p = p->next;
        if (!p)
            throw "溢出";
    }
    return p;
}

template<class T>
int LinkList<T>::Locate(T x){
    int ans = 0;
    Node<T> *p = front->next;
    while(p){
        ans++;
        if (p->data == x) // 重载
            return ans;
        p = p-> next;
    }
    return -1;
}

template<class T>
void LinkList<T>::Insert(int i,T x){
   
    Node<T> *p = front;
    Node<T> *tmp = new Node<T>;
    tmp->data = x;
    int count = 1;
    while(p){
        if(count == i){
            tmp->next = p->next;
            p->next = tmp;
            break;
        }
        count++;
        p = p -> next;
    }
    if(p == NULL and count == i)//这种写法的问题就是如何保证我第i-1个数存在
    throw "位置异常";
    if(count < i || i < 1)
    throw"位置异常";
}
//使用Get的写法
template <class T>
void LinkList<T>::Insert1(int i, T x){
    Node<T> *p = front;
    if(i!=1) p = Get(i-1);//这里细节一下。如果是1就是更新头结点,为了防止Get函数抛出异常,一定要判断
    if(p){

        Node<T> tmp = new Node<T>;
        tmp->data = x;
        tmp->next = p->next;
        p->next = tmp;
    }
    else
    throw"位置异常";
}
/*
如果 给定某节点p 要求在该节点后插入,那么流程:
new --> new.data --> new->next = p->next --> p->next = new;
对于前插操作流程
只需 交换p 与 new的值

*/
template<class T>
T LinkList<T>::Delete(int i){
    Node <T> *p = front;
    if(i!=1) p = Get(i-1);
    p->next = p->next->next;
    T x = del->data;
    delete p;
    return x;
}
循环链表

使用尾指针就够了rear->next 就是头指针、

双链表

template<class T>
struct Node
{
   T data;
   Node<T> * prior;
   Node<T> * next;
};
//p后插入q

q->prior = p; 1️⃣
p->next->prior = q; 2️⃣
q->next = p->next; 3️⃣
p ->next = q;4️⃣
// ⚠️ 2️⃣ 3️⃣ 一定要在 4️⃣前面

 // 删除p的后继
q = p->next 1️⃣
p->next->next->prior = p; 2️⃣
p->next = p->next->next 3️⃣
// ⚠️ 1️⃣一定要在3️⃣前面
// 删除p所指的节点
思路:交换 p 与 next 的值 == 删除p的后继