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");
}