数据结构-链表

链表

定义: 链表在物理内存上是一种非连续的存储结构,数据元素的逻辑顺序是由链表的指针链接来实现的。

链表的优点 1.插入和删除的效率高,只需要改变指针的指向就可以进行插入和删除。2.内存利用率高,不会浪费内存,可以使用内存中细小的不连续的空间,只有在需要的时候才去创建空间。大小不固定,拓展很灵活。

链表的缺点 :查找的效率低,因为链表是从第一个节点向后遍历查找。

在这里插入图片描述

链表的基本操作:

  • 初始化
  • 创建
  • 是否为空
  • 链表的个数
  • 清空链表
  • 返回给定位置的相应元素
  • 查找
  • 删除
  • 插入

链表的创建及初始化

创建链表之前,我们首先得知道链表结点的构成,它由一个指针域跟一个数据域构成,指针域的作用就是指明下一个地址的信息;

template<class T>
class linkNode{
public:
    T data_;
    linkNode *next_;
    
public:
    linkNode() : next_(nullptr) {}
    linkNode( T d ) : data_(d), next_(nullptr) {}
    linkNode( T d, linkNode *ne ) : data_(d), next_(ne) {}
    ~linkNode(){ next_ = nullptr; }
};

我们现在有了结点类之后,就继续写链表类,当我们声明一个链表的时候,我们就初始化一个头节点,这个头节点可以作为链表的第一个元素,也可以只做头结点。

template<class T>
class List{
private:
    linkNode<T> *head_;
    int length_;

public:
    List() : length_(0){
        head_ = new linkNode<T>();
    }
    ~List();

public:

};

template<class T>
List<T>::~List(){
    linkNode<T> *t;
    while( head_ != nullptr ){
        t = head_;
        head_ = head_->next_;
        delete t;
    }
}

链表的个数

我们在链表的成员变量里设置了 length,我们直接返回这个值就行

template <class T>
int List<T>::length(){
    return length_;
}

判断是否为空

只需要判断 length 是否为 0

template <class T>
bool List<T>::empty(){
    return length_();
}

清空链表

我们调用析构函数就能做到,不过我们需要再把头节点给申请出来

template <class T>
void List<T>::clear(){
    this->~List();
    head_ = new linkNode<T>();
    length_ = 0;
}

返回给定位置的相应元素

判断位置的范围是否在链表的长度里面,然后我们再遍历链表拿到相应位置的元素

template <class T>
T List<T>::get( int idx ){
    if( idx > length_ || idx <= 0){
        return nullptr;
    }
    int cnt = 0;
    linkNode<T> *p = head_;

    while( p != nullptr ){
        cnt ++;
        if( cnt == idx ){
            return p->data_;
        }
        p = p->next_;
    }

    return nullptr;
}

查找

循环遍历整个链表,有就返回相应位置;没有返回 0 or -1

template <class T>
int List<T>::find( T x ){
    int cnt = 0;
    linkNode<T> *p = head_;

    while( p != nullptr ){
        cnt ++;
        if( p->data_ == x ){
            return cnt;
        }
        p = p->next_;
    }
    return -1;
}

删除

判断删除的范围是否在合理范围内,然后判断是否为头结点,最后修改被删除结点的指针指向;

template <class T>
bool List<T>::erase( int idx ){
    if( idx <= 0 || idx > length_ ){
        idx = length_;
    }
    int cnt = 0;
    linkNode<T> *p = head_, *t = nullptr;

    while( p != nullptr ){
        if( ++ cnt == idx ){
            break;
        }
        t = p;
        p = p->next_;
    }

    if( t != nullptr ){
        t->next_ = p->next_;
        delete p;
    }else{
        t = p->next_;
        head_ = t;
        delete p;
    }
    length_ --;
    return true;
}

插入

插入的时候看是否在头结点,我们要更新头结点,其他情况就是先把下一个结点的指针赋值给插入的结点,再把下一个指向插入的就行;

template <class T>
bool List<T>::insert( T x, int idx ){
    if( idx <= 0 || idx > length_ ){
        idx = length_;
    } 
    int cnt = 0;
    linkNode<T> *p = head_, *t;

    if( length_ == 0 ){
        head_->data_ = x;
        length_ ++;
        return true;
    }

    while( p != nullptr ){
        if( ++ cnt == idx )
            break;
        
        p = p->next_;
    }


    t = new linkNode<T>( x, p->next_ );
    p->next_ = t;
    
    length_ ++;
    return true;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值