【本文谢绝转载原文来自http://990487026.blog.51cto.com】
数据结构与算 5:C++ 顺序/链式存储,栈 模板类实现 C++ 顺序存储模板类的实现[面试重要] C++ 链式存储模板类的实现[面试重要] C++ 链式存储模板类,载入指针 c++ 栈的链式存储实现(模板类嵌套模板类),编译问题教训[重要]
C++ 顺序存储模板类的实现[面试重要]
项目文件:
chunli@http://990487026.blog.51cto.com~/c++$ tree . ├── main.cpp ├── seqlist.cpp └── seqlist.h 0 directories, 4 files ================================
main.cpp文件
chunli@http://990487026.blog.51cto.com~/c++$ cat main.cpp
//C++ 构建模板类 顺序存储
#include
#include
#include
#include "seqlist.cpp"
using namespace std;
struct Teacher
{
char name[64];
int age;
};
void fun()
{
int i = 0;
struct Teacher tmp;
struct Teacher t1; t1.age = 31;
struct Teacher t2; t2.age = 32;
struct Teacher t3; t3.age = 33;
seqlist list(10);//创建顺序表
list.insert(t1,0);//头插法
list.insert(t2,0);//头插法
list.insert(t3,0);//头插法
//遍历链表
for(i=0;i 0)
{
list.del(0,tmp);////头删除
cout <
seqlist.cpp文件
chunli@http://990487026.blog.51cto.com~/c++$ cat seqlist.cpp #include#include "seqlist.h" template seqlist ::seqlist(int Capacity) { this->pArray = new T[Capacity]; this->capacity = Capacity; this->len = 0; } template seqlist ::~seqlist(void) { delete [] this->pArray; this->pArray = NULL; this->capacity = 0; this->len = 0; } template int seqlist ::getLen() { return this->len; } template int seqlist ::getCapacity() { return this->capacity; } template int seqlist ::insert(T &t,int pos) { int i = 0; if(pos <0) { return -1; } for(i=this->len;i>pos;i--) { pArray[i] = pArray[i-1]; } pArray[i] = t;//STL元素保存时,通过复制机制实现的,你的类要可以复制才行 this->len++; return 0; } template int seqlist ::get(int pos,T &t) { if(pos <0) { return -1; } t = pArray[pos]; return 0; } template int seqlist ::del(int pos,T &t) { int i = 0; t = pArray[pos]; for(i=pos+1;i len;i++) { pArray[i-1] = pArray[i]; } this->len--; return 0; } template int seqlist ::clear()//回到初始状态 { this->len = 0; return 0; } chunli@http://990487026.blog.51cto.com~/c++$
seqlist.h文件
chunli@http://990487026.blog.51cto.com~/c++$ cat seqlist.h
#pragma once
template
class seqlist
{
public:
seqlist(int Capacity);
~seqlist(void);
int getLen();
int getCapacity();
int insert(T &t,int pos);
int get(int pos,T &t);
int del(int pos,T &t);
int clear();//清空链表
private:
int len;
int capacity;
T *pArray;
};
chunli@http://990487026.blog.51cto.com~/c++$
编译运行:
chunli@http://990487026.blog.51cto.com~/c++$ g++ main.cpp -Wall && ./a.out 33 get 32 get 31 get 33 del 32 del 31 del chunli@http://990487026.blog.51cto.com~/c++$
C++ 链式存储模板类的实现[面试重要]
项目文件:
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ tree . ├── linklist.cpp ├── linklist.h └── main.cpp 0 directories, 3 files
linklist.cpp 文件
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ cat linklist.cpp
#include
#include "linklist.h"
template
LinkList::LinkList(void)
{
this->head = new Node;
this->head->next = NULL;//初始化
this->length =0;//初始化
}
template
LinkList::~LinkList(void)
{
Node *tmp = NULL;
while(this->head)
{
tmp = this->head->next;
delete head;
this->head = tmp;
}
this->length = 0;
this->head =NULL;
}
template
int LinkList::clear(void)
{
Node *tmp = NULL;
while(this->head)
{
tmp = this->head->next;
delete head;
this->head = tmp;
}
this->length = 0;
this->head = new Node;
this->head->next = NULL;//初始化
this->length =0;//初始化
return 0;
}
template
int LinkList::len(void)
{
return this->length;
}
template
int LinkList::insert(T &t,int pos)
{
Node *current = this->head;
for(int i = 0;inext;
}
Node *node = new Node;
if(node == NULL)
{
return -1;
}
node->t = t;//缓冲外部数据,调用拷贝构造函数
node->next = current->next;//让新节点连接后续表
current->next = node;
this->length++;
return 0;
}
template
int LinkList::get(int pos,T &t)
{
Node *current = NULL;
current = this->head;
for(int i = 0;inext;
}
t = current->next->t;//把缓存的节点给他
return 0;
}
template
int LinkList::del(int pos,T &t)
{
Node *current = this->head;
for(int i = 0;inext;
}
Node *ret = current->next;//被删除的元素
t = ret->t;////把缓存的节点给他
current->next = ret->next;
this->length--;
delete ret;//释放内存
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$
linklist.h文件
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ cat linklist.h
#pragma once
//模板类里面,在插入元素的时候,应该把每一个t保存起来
template
struct Node
{
T t;
Node *next;//搞成链表
};
template
class LinkList
{
public:
LinkList();
~LinkList();
int clear();
int len();
int insert(T &t,int pos );
int get (int pos,T &t);
int del(int pos,T &t);
private:
Node *head;//指向链表的头指针
int length;
};
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$
main.cpp文件
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ cat main.cpp
#include
#include
#include
#include "linklist.cpp"
using namespace std;
struct Teacher
{
char name[64];
int age;
};
int main()
{
int i = 0;
struct Teacher tmp;
struct Teacher t1; t1.age = 31;
struct Teacher t2; t2.age = 32;
struct Teacher t3; t3.age = 33;
LinkList list;//实例化 链式储存类
list.insert(t1,0);//头插法
list.insert(t2,0);//头插法
list.insert(t3,0);//头插法
//遍历链表
for(i=0;i 0)
{
list.del(0,tmp);////头删除
cout <
编译运行:
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类
$ g++ main.cpp linklist.cpp -Wall && ./a.out
33 get
32 get
31 get
33 del
32 del
31 del
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$
C++ 链式存储模板类,载入指针
linklist.cpp,linklist.h文件不变的
以下是main程序:
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ cat main.cpp
#include
#include
#include
#include "linklist.cpp"
using namespace std;
struct Teacher
{
char name[64];
int age;
};
int main()
{
int i = 0;
struct Teacher *tmp = NULL;
struct Teacher t1; t1.age = 31;
struct Teacher t2; t2.age = 32;
struct Teacher t3; t3.age = 33;
struct Teacher *p1 = &t1;
struct Teacher *p2 = &t2;
struct Teacher *p3 = &t3;
LinkList list;//实例化 链式储存类
list.insert(p1,0);//头插法
list.insert(p2,0);//头插法
list.insert(p3,0);//头插法
//遍历链表
for(i=0;iage <<" get\n";
}
list.clear();// 清空链表
list.insert(p1,0);//头插法
list.insert(p2,0);//头插法
list.insert(p3,0);//头插法
//循环删除
while(list.len() > 0)
{
list.del(0,tmp);////头删除
cout <age <<" del\n";
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$ g++ main.cpp linklist.cpp -Wall && ./a.out
33 get
32 get
31 get
33 del
32 del
31 del
chunli@http://990487026.blog.51cto.com~/c++/linklist_链式存储模板类$
c++ 栈的链式存储实现(模板类嵌套模板类),编译问题教训[重要]
项目文件:
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ tree . ├── linklist.cpp ├── linklist.h ├── LinkStack.cpp ├── LinkStack.h └── main.cpp 0 directories, 5 files
linklist.cpp 文件
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ cat linklist.cpp #include#include "linklist.h" template LinkList ::LinkList(void) { this->head = new Node ; this->head->next = NULL;//初始化 this->length =0;//初始化 } template LinkList ::~LinkList(void) { Node *tmp = NULL; while(this->head) { tmp = this->head->next; delete head; this->head = tmp; } this->length = 0; this->head =NULL; } template int LinkList ::clear(void) { Node *tmp = NULL; while(this->head) { tmp = this->head->next; delete head; this->head = tmp; } this->length = 0; this->head = new Node ; this->head->next = NULL;//初始化 this->length =0;//初始化 return 0; } template int LinkList ::len(void) { return this->length; } template int LinkList ::insert(T &t,int pos) { Node *current = this->head; for(int i = 0;i next; } Node *node = new Node ; if(node == NULL) { return -1; } node->t = t;//缓冲外部数据 node->next = current->next;//让新节点连接后续表 current->next = node; this->length++; return 0; } template int LinkList ::get(int pos,T &t) { Node *current = NULL; current = this->head; for(int i = 0;i next; } t = current->next->t;//把缓存的节点给他 return 0; } template int LinkList ::del(int pos,T &t) { Node *current = this->head; for(int i = 0;i next; } Node *ret = current->next;//被删除的元素 t = ret->t;////把缓存的节点给他 current->next = ret->next; this->length--; delete ret;//释放内存 return 0; } chunli@http://990487026.blog.51cto.com~/c++/link_stack$
linklist.h 文件
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ cat linklist.h
#pragma once
//模板类里面,在插入元素的时候,应该把每一个t保存起来
template
struct Node
{
T t;
Node *next;//搞成链表
};
template
class LinkList
{
public:
LinkList(void);
~LinkList(void);
int clear(void);
int len(void);
int insert(T &t,int pos );
int get (int pos,T &t);
int del(int pos,T &t);
private:
Node *head;//指向链表的头指针
int length;
};
chunli@http://990487026.blog.51cto.com~/c++/link_stack$
LinkStack.cpp 文件
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ cat LinkStack.cpp
#include
#include "LinkStack.h"
#include "linklist.cpp"//不要包含linklist.h,编译模板类包含linklist.cpp,不然老是报错找不到函数
template
LinkStack::LinkStack(void)
{
this->list = new LinkList; //创建栈就相当于创建线性表
}
template
LinkStack::~LinkStack(void)
{
clear();
delete list;
list = NULL;
}
template
void LinkStack::clear()
{
list->clear();
}
template
int LinkStack::push(T &t)
{
return list->insert(t,0); //向栈中添加元素
}
template
int LinkStack::pop(T &t)
{
return this->list->del(0,t);//传出元素,删除头部元素
}
template
int LinkStack::top(T &t)
{
return this->list->get(0,t);//获取头部元素
}
template
int LinkStack::size()
{
return this->list->len();
}
chunli@http://990487026.blog.51cto.com~/c++/link_stack$
LinkStack.h 文件
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ cat LinkStack.h
#pragma once
#include "linklist.h"
template
class LinkStack
{
public:
LinkStack(void);
~LinkStack(void);
void clear();
int push(T &t);
int pop(T &t);
int top(T &t);
int size();
private:
LinkList *list;//实例化一个链表
};
chunli@http://990487026.blog.51cto.com~/c++/link_stack$
main.cpp 文件
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ cat main.cpp
/*
g++ 编译模板类 ,老是报错,烦啊!!!
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ g++ main.cpp LinkStack.cpp linklist.cpp
/tmp/ccd3WOZY.o: In function `LinkStack::LinkStack()':
main.cpp:(.text._ZN9LinkStackI7TeacherEC2Ev[_ZN9LinkStackI7TeacherEC5Ev]+0x20): undefined reference to `LinkList::LinkList()'
/tmp/ccd3WOZY.o: In function `LinkStack::~LinkStack()':
main.cpp:(.text._ZN9LinkStackI7TeacherED2Ev[_ZN9LinkStackI7TeacherED5Ev]+0x29): undefined reference to `LinkList::~LinkList()'
/tmp/ccd3WOZY.o: In function `LinkStack::push(Teacher&)':
main.cpp:(.text._ZN9LinkStackI7TeacherE4pushERS0_[_ZN9LinkStackI7TeacherE4pushERS0_]+0x27): undefined reference to `LinkList::insert(Teacher&, int)'
/tmp/ccd3WOZY.o: In function `LinkStack::top(Teacher&)':
main.cpp:(.text._ZN9LinkStackI7TeacherE3topERS0_[_ZN9LinkStackI7TeacherE3topERS0_]+0x24): undefined reference to `LinkList::get(int, Teacher&)'
/tmp/ccd3WOZY.o: In function `LinkStack::size()':
main.cpp:(.text._ZN9LinkStackI7TeacherE4sizeEv[_ZN9LinkStackI7TeacherE4sizeEv]+0x17): undefined reference to `LinkList::len()'
/tmp/ccd3WOZY.o: In function `LinkStack::pop(Teacher&)':
main.cpp:(.text._ZN9LinkStackI7TeacherE3popERS0_[_ZN9LinkStackI7TeacherE3popERS0_]+0x24): undefined reference to `LinkList::del(int, Teacher&)'
/tmp/ccd3WOZY.o: In function `LinkStack::clear()':
main.cpp:(.text._ZN9LinkStackI7TeacherE5clearEv[_ZN9LinkStackI7TeacherE5clearEv]+0x17): undefined reference to `LinkList::clear()'
collect2: error: ld returned 1 exit status
chunli@http://990487026.blog.51cto.com~/c++/link_stack$
g++ 编译模板类的两种方式
关于模板类声明与实现分离(即声明放在.h文件,实现放在.cpp文件)的测试。
最近在写模板类的时候,分开编译模板声明和模板实现老实编译不过。看提示应该是链接不到实现的函数。
原来原因是模板的具体定义要在模板参数确定了之后才能实例化。
而在模板实例化的过程中(比如在main函数中,但只包含模板声明函数)。包含实例化的.cpp文件编译成.o文件,留了类函数的入口地址等待填充。
一般,包含普通函数的.cpp文件编译成.o文件时。函数是确定的,能编译成二进制代码。然后就有函数入口地址可以让链接程序填入调用了这个函数的.o文件中。然后函数调用就成功了。
但是,对于模板类的实现。编译成.o文件时,仍然没有实例化。就是说模板类的实现函数不知道具体的模板函数是什么,不能实例化成一个真正的类型.
(比如Vector a ; //参数实例化成int,vector为一个类型( 和内置类型double一样了 ))。
但是没有实例化前,函数是不确定的。就是还没有编译成二进制文件。所以没有函数的入口地址提供。由于没有入口地址,链接程序在帮main函数找实例化成具体类型的模板找实现函数时找不到,就提示链接错误了。
既然知道哪里粗了问题,就可以解决问题了。解决的办法就是让实例化了模板的.cpp文件可以看到函数实现就行了。
1、直接把函数声明和函数实现全部放在同一个.h文件里面。这样引用.h文件的时候,声明和实现都直接展开在实例化的.cpp文件里面这样编译的时候就能找到函数的入口地址了。
2、函数声明和函数实现分开实现。在实例化模板的地方#include "xxx.cpp",即直接包含.cpp文件,这样也能找到函数入口。本程序引用这种方法.
*/
#include
#include "LinkStack.cpp"
using namespace std;
struct Teacher
{
char name[64];
int age;
};
int main()
{
//创建栈
LinkStack stack;//实例化类
struct Teacher tmp;
struct Teacher t1; t1.age = 31;
struct Teacher t2; t2.age = 32;
struct Teacher t3; t3.age = 33;
//入栈
stack.push(t1);
stack.push(t2);
stack.push(t3);
//谁是栈顶
stack.top(tmp);
cout << tmp.age<<" top \n";
//清空栈
stack.clear();
//入栈
stack.push(t1);
stack.push(t2);
stack.push(t3);
//栈的删除
while(stack.size())
{
stack.pop(tmp);
cout << tmp.age<<" pop \n";
}
return 0;
}
chunli@http://990487026.blog.51cto.com~/c++/link_stack$
编译运行:
chunli@http://990487026.blog.51cto.com~/c++/link_stack$ g++ main.cpp LinkStack.cpp linklist.cpp -Wall && ./a.out 33 top 33 pop 32 pop 31 pop chunli@http://990487026.blog.51cto.com~/c++/link_stack$
【本文谢绝转载原文来自http://990487026.blog.51cto.com】