数据结构之 单链表 模板类

2017 10 25更新:
写完了的 “单链表模板类”如下图所示(还差一个按照规则升序或者降序添加数据的函数insertSeq,明天可以完成—-26号写完了)

#include<iostream>

#ifndef _H_MYCHAIN_H
#define _H_MYCHAIN_H

template<class T>
class mychain;

template<class T>
struct snode
{
    struct snode<T>* next;
    T val;
};

template<class T>
class mychain
{
public:
    /构造函数与析构函数
    mychain(void);////默认构造函数
    mychain(const mychain<T>& otherChain);////拷贝构造函数
    ~mychain();////析构函数

    ////增
    void addHead(const T val);////头插
    int insert(const int pos, const T val);////中间插入数据,成功则返回插入位置的索引,从0开始,失败则返回-1,如果索引超出范围,也返回-1
    int insertSeq(const T val, bool isAscend);///让元素按照升序或者降序插入到满足条件的第一个元素后面,返回插入位置的索引
    int push_back(const T val);////尾插数据,返回插入的索引

    /////删
    int del(const int pos);////删除指定索引的元素,返回被删除的元素的索引,失败则返回-1
    int remove(T val);////移除指定值得第一个元素,返回元素原来在的索引,不存在则返回-1
    int removeAllVal(const T val);////移除所有的指定数值的元素,返回移除的个数
    bool clear(void);

    /////改
    int modify(const int pos, const T val_new);////修改指定索引处的数值为val_new,返回替换位置的索引,如果索引不存在则返回-1
    int replace(const T val_old, const T val_new);////替换第一个找到的指定数值的元素为val_new,返回其索引,如果指定数值不存在,则返回-1
    int replaceAll(const T val_old, const T val_new);////替换所有的指定数值为val_new,返回替换的个数

    ////查
    int find(const T val);////查找指定数值的元素的索引,不存在则返回-1
    bool getAt(const int pos, T& val);////获取指定索引的元素的数值,存放在val引用中,不存在则返回false

    ////为了重载输出操作符
    void output(std::ostream& out);

    /////想要实现但是没有实现的
    //friend std::ostream& operator<<(std::ostream, const mychain<T>& chain);
    //struct snode<T>* getPtrByIndex(int pos);
    //struct snode<T>* getPtrByVal(const T val);

private:
    struct snode<T>* m_pHead;
};

template<class T>
std::ostream& operator<<(std::ostream& out, mychain<T>& mc);

#endif

/////构造函数与析构函数
template<class T>
mychain<T>::mychain(void)////默认构造函数
{
    m_pHead = NULL;
}

template<class T>
mychain<T>::mychain(const mychain<T>& otherChain)////拷贝构造函数
{
    if(NULL  == otherChain.m_pHead)
    {
        m_pHead = NULL;
        return;
    }
    ////以下是被拷贝对象不为空的情况
    bool isFirst = true;
    struct snode<T> *p_pre = NULL;
    struct snode<T> *p = otherChain.m_pHead;
    while (NULL != p)
    {
        if(isFirst)
        {
            m_pHead = new struct snode<T>;
            m_pHead->val = p->val;
            p_pre = m_pHead;
            isFirst = false;
        }
        else
        {
            p_pre->next =  new struct snode<T>;
            p_pre = p_pre->next;
            p_pre->val = p->val;
        }
        p = p->next;
    }
    p_pre->next = NULL;
}

template<class T>
mychain<T>::~mychain()////析构函数
{
    if(NULL != m_pHead)
    {
        struct snode<T>* p = m_pHead;
        m_pHead = NULL;
        struct snode<T>* p_nxt;
        while (NULL != p)
        {
            p_nxt = p->next;
            delete p;
            p = p_nxt;
        }
    }
}

////增
template<class T>
void mychain<T>::addHead(const T val)////头插
{
    struct snode<T>* p = new struct snode<T>;
    p->val = val;
    p->next = m_pHead;
    m_pHead = p;
    p = NULL;////防止野指针(感觉其实没必要)
}

template<class T>
int mychain<T>::insert(const int pos, const T val)////中间插入数据,原来的位置的数据向后移动,成功则返回插入位置的索引,从0开始,失败则返回-1,如果索引超出范围,也返回-1
{
    if(0 == pos)/////要求的索引为0的时候,不管原来的链表是不是为空,都直接头插
    {
        addHead(val);
        return 0;
    }
    else//////但是如果不是在0的位置的话,那就需要考察是不是超出索引了
    {
        struct snode<T>* p = m_pHead;
        for(int ii = 0;(ii < pos-1) && (NULL != p); ii++)
        {
            p = p->next;
        }
        if(NULL != p)
        {
            struct snode<T>* p_next = p->next;
            p->next = new struct snode<T>;
            p = p->next;
            p->val = val;
            p->next = p_next;
            return pos;
        }
        else
        {
            return -1;
        }
    }
}

template<class T>
int mychain<T>::insertSeq(const T val, bool isAscend)
{
    if (NULL == m_pHead)
    {
        addHead(val);
        return 0;
    }
    if ((val < m_pHead->val && isAscend)||(!isAscend && val > m_pHead->val))
    {
        addHead(val);
        return 0;
    }
    struct snode<T>* p = m_pHead;
    struct snode<T>* p_nxt = NULL;
    int cnt = 0;
    while (NULL != p)
    {
        cnt = cnt + 1;
        p_nxt = p->next;
        if (NULL != p_nxt)
        {
            if ( (val > p->val && val <= p_nxt->val && isAscend) || 
                (val < p->val && val >= p_nxt->val && !isAscend))
            {
                break;
            }
        }
        else
        {
            break;
        }
        p = p_nxt;
    }
    p->next = new struct snode<T>;
    p = p->next;
    p->val = val;
    p->next = p_nxt;
    return cnt;
}

template<class T>
int mychain<T>::push_back(const T val)////尾插数据,返回插入的索引
{
    if (NULL == m_pHead)
    {
        addHead(val);
        return 0;////头插的索引为0
    }
    /////下面是非头插的情况
    struct snode<T>* p = m_pHead;
    int cnt = 1;
    while(NULL != p->next)
    {
        cnt = cnt + 1;
        p = p->next;
    }
    p->next = new struct snode<T>;
    p = p->next;
    p->val = val;
    p->next = NULL;
    return cnt;
}

/////删
template<class T>
int mychain<T>::del(const int pos)////删除指定索引的元素,返回被删除的元素的索引,失败则返回-1
{
    if(0 == pos)
    {
        if(NULL == m_pHead)
        {
            return -1;
        }
        else
        {
            struct snode<T>* p = m_pHead->next;
            delete m_pHead;
            m_pHead = p;
        }
    }
    else
    {
        struct snode<T>* p = m_pHead;
        for(int ii = 0; (ii < pos - 1) && (NULL != p); ii ++)
        {
            p = p->next;
        }
        if(NULL == p)
        {
            return -1;/////前面的元素都不存在
        }
        else
        {
            if(NULL == p->next)
            {
                return -1;//////想要被删的元素不存在
            }
            else
            {
                struct snode<T>* p_del = p->next;
                p->next = p_del->next;
                delete p_del;
            }
        }
    }
    return pos;
}

template<class T>
int mychain<T>::remove(T val)////移除指定值得第一个元素,返回元素原来在的索引,不存在则返回-1
{
    struct snode<T>* p = m_pHead;
    int cnt = 0;
    if (val == p->val)
    {
        m_pHead = m_pHead->next;
        delete p;
        return cnt;
    }
    struct snode<T>* p_nxt = NULL;
    while (NULL != p)
    {
        p_nxt = p->next;
        cnt = cnt + 1;
        if (NULL != p_nxt)
        {
            if (val == p_nxt->val)
            {
                p->next = p_nxt->next;
                delete p_nxt;
                p_nxt = NULL;
                return cnt;
            }
        }
        p = p_nxt;
    }
    return -1;
}

template<class T>
int mychain<T>::removeAllVal(const T val)////移除所有的指定数值的元素,返回移除的个数
{
    struct snode<T>* p = m_pHead;
    int cnt = 0;////删除的元素数目
    struct snode<T>* p_nxt = NULL;
    while (NULL != p)
    {
        p_nxt = p->next;
        if (NULL != p_nxt)
        {
            if (val == p_nxt->val)
            {
                cnt = cnt + 1;
                p->next = p_nxt->next;
                delete p_nxt;
                continue;
            }
        }
        p = p_nxt;
    }
    p = m_pHead;
    if (val == m_pHead->val)
    {
        m_pHead = m_pHead->next;
        delete p;
        cnt = cnt + 1;
    }
    return cnt;
}

template<class T>
bool mychain<T>::clear(void)
{
    if(NULL != m_pHead)
    {
        struct snode<T>* p = m_pHead;
        m_pHead = NULL;
        struct snode<T>* p_nxt;
        while (NULL != p)
        {
            p_nxt = p->next;
            delete p;
            p = p_nxt;
        }
    }
}

/////改
template<class T>
int mychain<T>::modify(const int pos, const T val_new)////修改指定索引处的数值为val_new,返回替换位置的索引,如果索引不存在则返回-1
{
    struct snode<T>* p = m_pHead;
    for (int ii = 0; (ii < pos) && (NULL != p); ii++)
    {
        p = p->next;
    }
    if(NULL == p)
    {
        return -1;
    }
    else
    {
        p->val = val_new;
        return pos;
    }
}

template<class T>
int mychain<T>::replace(const T val_old, const T val_new)////替换第一个找到的指定数值的元素为val_new,返回其索引,如果指定数值不存在,则返回-1
{
    struct snode<T>* p = m_pHead;
    int cnt = 0;
    while (NULL != p)
    {
        if (val_old == p->val)
        {
            p->val = val_new;
            return cnt;
        }
        p = p->next;
        cnt = cnt + 1;
    }
    return -1;
}

template<class T>
int mychain<T>::replaceAll(const T val_old, const T val_new)////替换所有的指定数值为val_new,返回替换的个数
{
    struct snode<T>* p = m_pHead;
    int cnt = 0;
    while (NULL != p)
    {
        if (val_old == p->val)
        {
            p->val = val_new;
            cnt = cnt + 1;
        }
        p = p->next;
    }
    return cnt;
}

////查

template<class T>
int mychain<T>::find(const T val)////查找指定数值的元素的索引,不存在则返回-1。索引从零开始计算
{
    struct snode<T>* p = m_pHead;
    int cnt = 0;
    while (NULL != p)
    {
        if(val == p->val)
        {
            return cnt;
        }
        cnt = cnt + 1;
        p = p->next;
    }
    return -1;
}

template<class T>
bool mychain<T>::getAt(const int pos, T& val)////获取指定索引的元素的数值,存放在val引用中,不存在则返回false
{
    struct snode<T>* p = m_pHead;
    for (int ii = 0; (ii < pos) && (NULL != p); ii++)
    {
        p = p->next;
    }
    if(NULL != p)
    {
        val = p->val;
        return true;
    }
    return false;
}

////为了重载输出操作符

template<class T>
void mychain<T>::output(std::ostream& out)
{
    struct snode<T>* p = m_pHead;
    while (NULL != p)
    {
        out<<p->val <<" ";
        p = p->next;
    }
    out<<std::endl;
}

template<class T>
std::ostream& operator<<(std::ostream& out, mychain<T>& mc)
{
    mc.output(out);
    return out;
}

下面是该模板类的测试函数,针对每一个函数进行测试

#include "mychain.cpp"
#include<iostream>

void main(void)
{
    mychain<int> mc;
    for (int ii = 0; ii < 10; ii++)
    {
        if(ii%2 == 0)
        {
            mc.push_back(ii);
        }
        else
        {
            mc.addHead(ii);
        }
    }
    std::cout<<mc<<std::endl;

    mc.insert(3,8);
    mc.insert(1,4);
    mc.insert(3,8);
    std::cout<<mc<<std::endl;

    mc.replaceAll(8,4);
    std::cout<<mc<<std::endl;

    mc.removeAllVal(4);
    std::cout<<mc<<std::endl;

    mychain<int> mc1;
    for (int ii = 0; ii < 10; ii++)
    {
        std::cout<<mc1.insertSeq(ii,false)<<"  ";
    }
    std::cout<<std::endl;
    std::cout<<mc1<<std::endl;



    std::system("pause");
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值