阅读本文需要对顺序表有一定的了解,欢迎您的阅读。
首先介绍模板函数:顾名思义,就是一个模板让别的事物套用的,c++中的模板就是同一结构的不同类型套用的,举个简单例子,要使用这个结构的模板,int可以用,char也可以用,等等
好了不罗嗦了,直接上实现函数吧!
模板结构如下:
template<typename T> //模板函数,T为参数类型 class SeqList { public: SeqList(); SeqList(T *array, size_t size); SeqList(const SeqList &s); //现代写法 SeqList &operator=(SeqList s); ~SeqList(); void PushBack(const T& x); //尾增 void PopBack(); //尾删 void PushFount(const T& x); //头增 void PopFount(); //头删 void Insert(size_t pos, const T& x); //中间插入 void Erase(size_t pos); //中间删除 int Find(T x); //寻找 void PrintSeqList(); //输出 void _CheekCapacity(); //检查容量 private: T *_array; size_t _size; size_t _capaci; };
构造函数、赋值运算符重载函数:
template<typename T> SeqList<T>::SeqList() :_array(NULL), _size(0), _capaci(0) {} template<typename T> SeqList<T>::SeqList(T *array, size_t size) : _array(new T[size]), _size(size), _capaci(size) { //memcpy(_array, array, sizeof(T)*size); //当T为非基本类型时不能用memcpy for (size_t i = 0; i < size; i++) { _array[i] = array[i]; } } //template<typename T> //SeqList<T>::SeqList(const SeqList& s) //传统写法 // :_array(new T[s._size]), // _size(s._size), // _capaci(s._size) //{ // //memcpy(_array, s._array, sizeof(T)*_size); // for (size_t i = 0; i < size; i++) // { // _array[i] = array[i]; // } //} template<typename T> SeqList<T>::SeqList(const SeqList &s) //现代写法 :_array(NULL) { SeqList temp(s._array, s._size); swap(_array, temp._array); _size = s._size; _capaci = s._capaci; } template<typename T> SeqList<T>& SeqList<T>::operator=(SeqList s) { swap(s._array, _array); _size = s._size; _capaci = s._capaci; //swap(_size,s._size); //swap(_capaci,s._capaci); return *this; } //template<typename T> //SeqList<T>& SeqList<T>::operator=(const SeqList s) //{ // if (this != &s) // { // T *temp = new T[s._size]; // delete[]_array; // _array = temp; // _size = s._size; // _capaci = s._size; // for (size_t i = 0; i < _size; i++) // temp[i] = _array[i]; // } // return *this; //}
析构函数:
template<typename T> SeqList<T>::~SeqList() { if (_array) { delete[] _array; } }
插入删除函数:
template<typename T> void SeqList<T>::PushBack(const T& x) { _CheekCapacity(); _array[_size] = x; _size++; } template<typename T> void SeqList<T>::PopBack() { if (_size > 0) { _size--; } } template<typename T> void SeqList<T>::PushFount(const T& x) { _CheekCapacity(); for (int i = _size; i > 0; i--) { _array[i] = _array[i - 1]; } _array[0] = x; _size++; } template<typename T> void SeqList<T>::PopFount() { if (_size == 0) { cout << "空链表" << endl; } for (size_t i = 0; i < _size - 1; i++) { _array[i] = _array[i + 1]; } _size--; } template<typename T> void SeqList<T>::Insert(size_t pos, const T& x) { _CheekCapacity(); if (pos<_size) for (int i = _size; i > _size - pos; i--) { _array[i] = _array[i - 1]; } _array[pos - 1] = x; _size++; } template<typename T> void SeqList<T>::Erase(size_t pos) { if (_size == 0) { cout << "空链表,无需删除!" << endl; } for (int i = pos; i < _size; i++) { _array[i - 1] = _array[i]; } _size--; }
寻找值的函数、输出内容函数:
template<typename T> int SeqList<T>::Find(T x) { if (_size == 0) { cout << "空链表!" << endl; } for (int i = 0; i < _size; i++) { if (x == _array[i]) { return i + 1; } } return -1; } template<typename T> void SeqList<T>::PrintSeqList() { for (int i = 0; i < (int)_size; i++) cout << _array[i] << " "; cout << endl; }
检查容量和增容函数:
template<typename T> void SeqList<T>::_CheekCapacity() { if (_size >= _capaci) { _capaci = 2 * _capaci + 3; T* temp = new T[_capaci]; for (size_t i = 0; i < _size; i++) temp[i] = _array[i]; swap(_array, temp); } }
上述代码全部定义于我自定义的typetemp.h头文件中,并写在#ifndef _TYPETEMP_H__ #define _TYPETEMP_H__ 和 #endif之间
测试函数如下:
#include"SeqList.h" void test2() { cout << "使用 int 类型构造 :" << endl; cout << "s1:" << endl; SeqList<int> s1; s1.PushBack(1); s1.PushBack(2); s1.PushBack(3); s1.PushBack(4); s1.PushBack(5); s1.PrintSeqList(); cout << "s2:" << endl; SeqList<int> s2(s1); s2.PopBack(); s2.PrintSeqList(); cout << "s3:" << endl; SeqList<int> s3; s3 = s1; s3.PopFount(); s3.PrintSeqList(); } void test3() { cout << "使用 char 类型构造 :" << endl; cout << "s1:" << endl; SeqList<char> s1; s1.PushBack('a'); s1.PushBack('b'); s1.PushBack('c'); s1.PushBack('d'); s1.PushBack('e'); s1.PrintSeqList(); cout << "s2:" << endl; SeqList<char> s2(s1); s2.PopBack(); s2.PrintSeqList(); cout << "s3:" << endl; SeqList<char> s3; s3 = s1; s3.PopFount(); s3.PrintSeqList(); } void test4() { cout << "使用 string 类型构造 :" << endl; cout << "s1:" << endl; SeqList<string> s1; s1.PushBack("xxxx"); s1.PushBack("ssss"); s1.PushBack("aaaa"); s1.PushBack("dddd"); s1.PushBack("eeee"); s1.PrintSeqList(); cout << "s2:" << endl; SeqList<string> s2(s1); s2.PopBack(); s2.PrintSeqList(); cout << "s3:" << endl; SeqList<string> s3; s3 = s1; s3.PopFount(); s3.PrintSeqList(); } int main() { test2(); test3(); test4(); system("pause"); return 0; }
运行函数,查看结果:
注意事项:当使用基本类型,如int char float 等类型时,模板函数可以用memcpy,realloc 等涉及内存的函数;当时用非基本类型,如string 类型时,模板函数不能使用memcpy等涉及内存操作的函数,因为会产生程序崩溃等现象,原因是由于调用析构函数引起的,这里就不详加讨论,这篇文章里的函数都没有使用memcpy 等函数,这样函数还不是最优化的,优化方案我会在下一篇博客 <模板函数-类型萃取>里边解决,欢迎阅读,谢谢!
限于我目前的c++水平 仅能实现上述函数,欢迎大家阅读,如发现错误或者不足,恳请您给予批评指正,谢谢!