//stack 的基本操作
#include <iostream>
using namespace std;
const int maxn = 3;
typedef struct Stack
{
//NumType num;
int num;
}Stack;
int top = 0;//当前元素位置的上一个元素
Stack stack[maxn];
bool is_empty();
bool is_full();
int pop();
void push(const int &key);
int get_top();
bool make_empty(); int main()
{
int tmp;
cout << get_top() << " " << pop() << endl;// 这句话和以下存在相同的错误
cout << "Input a set of integers:(-1 is over)" << endl;
while(cin >> tmp)
{
if(tmp == -1) break;
push(tmp);
}
tmp = get_top();
cout << tmp << endl;
tmp = pop();
cout << tmp << endl;
//cout << pop() << " " << get_top() << endl;
//cout << get_top() << " " << pop() << endl;// 这样输出会发生很奇异的事情的
return 0;
}
// if stack is empty return true
bool is_empty()
{
return (top == 0);
}
// if stack is full return true
bool is_full()
{
return (top == maxn);
}
// pop the top number if not empty
int pop()
{
if(is_empty())
{
cout << "The Stack is empty,Cannot pop..." << endl;
return -1;
}
else
{
top --;
return stack[top].num;
} }
// push one number,if not full
void push(const int &key)
{
if(is_full())
{
cout << "The Stack is full,Cannot push..." << endl;
return;
}
else
{
stack[top].num = key;
top ++;
}
}
// get the top number,not pop
int get_top()
{
if(is_empty())
{
cout << "The Stack is empty,Cannot get top..." << endl;
return -1;
}
else
{
return stack[top-1].num;
}
}
bool make_empty()
{
top = 0;
}

/*

    学习心得:

    1、 此栈用链表实现,与上面的用数组实现不一样;用到了模板类Stack<DT>

    2、 此类用到了复制构造函数 Stack(const Stack<DT> &original),运算符重载函数

        Stack<DT>& operator = (const Stack<DT> &original)

    3、 初始化的默认构造方式Stack():top(NULL) {},记住类中声明的函数不能够有函数体的,

        可是空函数体(仅仅有{})是能够的(即默认构造函数;全部的成员变量是不能够初试化的,

        可是能够通过默认构造函数初始化,如Stack():top(NULL) {},或者定义为static。


    4、 &element引用作为參数时:(1)const Stack<DT> &original 作为不可变的变量的

        引用传递 (2)DT &top_element 函数的引用型參数作为返回值(能够实现多个返回值)

    5、 内联函数的引入,内联扩展是用来消除函数调用时的时间开销。它通经常使用于频繁

运行的函数。 一个小内存空间的函数非常受益,类似与宏定义,可是宏也有非常多的不尽人意的地方:

(1)宏不能訪问对象的私有成员。(2)宏的定义非常easy产生二义性。

    6、 template 和 typedef 不能同一时候使用的问题:模板不是类型!typedef仅仅能给

类型取别名。单独的Node是模板,而Node<int>是一个实实在在的类型。

usingkeyword能够给模板取别名!如:template<class T>

using Test = Node<T>;Test<int> t;

等价于:Node<int> t;

   7、 仅仅要定义了不论什么一种构造函数,就不会自己主动定义默认构造函数。假设此时要用到默认构造函数,

就必须手动定义默认构造函数。所谓默认构造函数,就是调用构造函数时,不必给出实參的构造函数。

8、 假设一个类中定义了不论什么一种构造函数,而没有定义默认构造函数,是不可以定义类的对象的如:class A{}; A  aa;(这是错误的)

可是A *pa;(这是合法的,由于只定义了一个指针,没有调用不论什么构造函数,不分配类对象的内存)

9:写一个空类;class a(){}  编译的时候会生成哪些函数?

默认构造函数

析构函数

拷贝构造函数

赋值运算符(operator=)

取址运算符(operator&)(一对,一个非const的,一个const的)

当然,全部这些仅仅有当被须要才会产生。比方你定义了一个类,但从来定义过该类的对象,也没使用过该类型的函数參数,那么基本啥也不会产生。在比方你从来没有进行过该类型对象之间的赋值,那么operator=不会被产生。

最后那一对取址运算符是用争议的, 我记得曾经是有一个贴讨论这个的,据说跟详细的编译器相关, 有的生成, 有的不生成, 仅仅有前四个

*/

class Empty
{
public:
Empty(); // 缺省构造函数 Empty(const Empty&); // 拷贝构造函数 ~Empty(); // 析构函数 Empty& perator=(const Empty&); // 赋值运算符 Empty* operator&(); // 取值运算符
const Empty* operator&() const; // 取值运算符 };

以下是模板类:

#include<iostream>
#include<string>
using namespace std;
//用"链表"实现栈
//入栈,出栈的时间复杂度为O(1)
//复制、清空和遍历栈的时间复杂度为O(n)
template<class DT>
//typedef struct Node// template 中不能用typedef
struct Node
{
DT info;
Node<DT> *next;
}; template<class DT>
class Stack
{
public:
Stack():top(NULL) {};// 初试化top的构造函数...初始化的默认方式
Stack(const Stack<DT> &original);
~Stack();
Stack<DT> &operator = (const Stack<DT> &original);
void push(const DT &element);
bool pop(DT &element);
bool peek(DT &top_element);// 得到栈顶的数据
bool is_empty() const;// is empty 没有满
void make_empty();
private:
Node<DT> *top,*pre;// 私有成员,指向当前成员,指向链表的头
inline void deepCopy(const Stack<DT> &original);//深复制
}; template<class DT>
Stack<DT>::Stack(const Stack<DT> &original)
{
deepCopy(original);
} template<class DT>
Stack<DT>::~Stack()
{
make_empty();// 直接条用类里面的函数
} template<class DT>
void Stack<DT>::push(const DT &element)
{
pre = new Node<DT>;
pre->info = element;
pre->next = top;
top = pre;
}// 前插入法,top指向链表的头结点 template<class DT>
Stack<DT>& Stack<DT>::operator =(const Stack<DT> &original)
{
deepCopy(original);
return this;
}// 运算符重载函数,返回的是引用
template<class DT>
bool Stack<DT>::pop(DT &element)
{
if(top == NULL)
return false;
else
{
element = top->info;
pre = top;
top = top->next;
delete pre;
pre = NULL;
}
//cout << "*****pop" << endl;
return true;
}
template<class DT>
bool Stack<DT>::peek(DT &top_element)
{
if(top == NULL)
return false;
else
{
top_element = top->info;
}
//cout << "***peek" << endl;
return true;
}
template<class DT>
bool Stack<DT>::is_empty() const
{
return (top == NULL);
}
template<class DT>
void Stack<DT>::make_empty()
{
if(top == NULL)
return;
while(top != NULL)
{
pre = top;
top = top->next;
delete pre;
pre = NULL;
}
}
template<class DT>
void Stack<DT>::deepCopy(const Stack<DT> &original)
{
Node<DT> *oriPtr = original.top;
Node<DT> *copyPtr = top = new Node<DT>;
copyPtr->info = oriPtr->info;
while(oriPtr->next != NULL)
{
copyPtr->next = new Node<DT>;// 经典!!!
copyPtr = copyPtr->next;
oriPtr = oriPtr->next;
copyPtr->info = oriPtr->info;
}
copyPtr->next = NULL;
} int main()
{
Stack<string> obj;// 模板类的构造函数
string str[5] = {"hello","the","world","welcome","to"};
string strTemp;
for(size_t ix=0;ix!=5;++ix)
{
obj.push(str[ix]);
obj.peek(strTemp);
cout<<strTemp<<",";
}
cout<<endl;
Stack<string> obj1(obj); //測试复制构造函数
for(size_t ix=0;ix!=5;++ix)
{
obj1.pop(strTemp);
cout<<strTemp<<",";
}
cout<<endl; if(obj1.is_empty())
cout<<"Stack is empty!"<<endl;
Stack<string> obj2(obj); //測试复制构造函数
obj2.make_empty();
if(obj2.is_empty())
cout<<"Stack is empty!"<<endl;
Stack<string> obj3 = obj; //測试重载“=”操作符
for(size_t ix=0;ix!=5;++ix)
{
obj3.pop(strTemp);
cout<<strTemp<<",";
}
cout<<endl; for(size_t ix=0;ix!=5;++ix)
{
obj.pop(strTemp);
cout<<strTemp<<",";
}
cout<<endl;
return 0;
}

/*

内联函数是使用inlinekeyword声明的函数,也成内嵌函数,它基本的作用是解决程序的执行

效率。使用内联函数的时候要注意:


1.递归函数不能定义为内联函数

2.内联函数一般适合于不存在while和switch等复杂的结构且仅仅有1~5条语句的小函数上,

否则编译系统将该函数视为普通函数。

3.内联函数仅仅能先定义后使用,否则编译系统也会把它觉得是普通函数。

4.对内联函数不能进行异常的接口声明。

*/

堆(stack) 之 c 和 c++模板实现(空类默认成员函数 初谈引用 内联函数)的更多相关文章

  1. 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板

    [源码下载] 不可或缺 Windows Native (16) - C++: 函数重载, 缺省参数, 内联函数, 函数模板 作者:webabcd 介绍不可或缺 Windows Native 之 C++ ...

  2. C++ primer(八)--内联函数 引用变量 引用传递函数参数 函数重载/模板/模板具体化

    一.内联函数     常规函数和内联函数的区别在于C++编译器如何将他们组合到程序中.编译过程的最终产品是可执行程序--由一组机器语言指令组成.运行程序时,操作系统将这些指令载入到计算机内存中,因此每 ...

  3. C++内联函数、函数模板之于头文件

    一.基本说明 C++标准中提到,一个编译单元是指一个.cpp文件以及它所include的所有.h文件,.h文件里的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件 ...

  4. 20140808 const和define区别 内联函数(inline) 栈和堆的地址分配 栈帧

    1.const和define区别 const有数据类型(不能改变的变量),define只是简单的字符串替换,没有数据类型. C++程序用const完全取代 define. const还可以类成员函数为 ...

  5. [C++ Primer Plus] 第8章、函数探幽(一)程序清单——内联、引用、格式化输入输出、模板、decltype

    程序清单8.1(inline内联函数) #include<iostream> using namespace std; inline double square(double x) {// ...

  6. 栈 堆 stack heap

    点餐 做菜 Stack and Heap 堆和栈的区别 - Grandyang - 博客园 https://www.cnblogs.com/grandyang/p/4933011.html 在和计算机 ...

  7. 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型

    小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...

  8. c++函数模板作为类的成员函数,编译报错LNK2019的解决方法

    为了使某个类的成员函数能对不同的参数进行相同的处理,需要用到函数模板,即template<typename T> void Function(). 编译时报错LNK2019 解决方法: 1 ...

  9. 如何让对象只在堆或者栈中分配空间ANDC++禁止一个类被继承

    在开始之前先来分析一下C++中的new运算符和operator new之间的关联. new:指我们在C++里通常用到的运算符,比如A* a = new A或者调用带参数的构造函数;  对于new来说, ...

随机推荐

  1. Java与模式:装饰(Decorator)模式

    装饰模式使用被装饰类的一个子类的实例.把client的调用委派到被装饰类,装饰模式的关键在于这样的扩展是全然透明的.   装饰模式在Java种使用也非常广泛,比方我们在又一次定义button.对话框等 ...

  2. SIMPLE QUERY几个原则

    1.减少查询对象的数据页(db block)数量. 尽量避免使用 * 用准确的列明减少不必要的一些资源浪费.   2.查看是否使用了index. 索引是SQL性能调优的重要手段,下面几个是有索引不能使 ...

  3. 14、USB摄像头(V4L2接口)的图片采集

    参考网站http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一.一些知识 1.V4L和V4L2. V4L是 ...

  4. 【例题3-6 UVA - 1584】Circular Sequence

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 不用真的把每一位都取出来. 用一个后缀的思想. 把原串复制一遍接在后面,然后把每个字符串 都当成一个长度为n的后缀就好了. 比较每个 ...

  5. 【Codeforces Round #185 (Div. 2) B】Archer

    [链接] 链接 [题意] 在这里输入题意 [题解] 概率水题. 枚举它是第几轮成功的. 直到满足精度就好 [错的次数] 1 [反思] long double最让人安心. [代码] #include & ...

  6. Android应用开发按下返回键退向后台执行

    转载请注明来源:http://blog.csdn.net/kjunchen/article/details/50429694 Android应用开发按下返回键退向后台执行 我们日常使用的非常多Andr ...

  7. js课程 1-5 js如何测试变量的数据类型

    js课程 1-5 js如何测试变量的数据类型 一.总结 一句话总结:用typeof()方法. 1.js如何判断变量的数据类型? 用typeof()方法. 13 v=10; 14 15 if(typeo ...

  8. linux下如何查找nginx配置文件的位置

    nginx的配置放在nginx.conf文件中,一般我们可以使用以下命令查看服务器中存在的nginx.conf文件. locate nginx.conf /usr/local/etc/nginx/ng ...

  9. 从程序员的角度分析微信小程序(编程语言:用到什么学什么)

    从程序员的角度分析微信小程序(编程语言:用到什么学什么) 一.总结 一句话总结:微信小程序原理就是用JS调用底层native组件,和React Native非常类似.(需要时,用到时再学) 1.选择语 ...

  10. js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global)

    js进阶正则表达式10-分组-多行匹配-正则对象的属性(小括号作用:分组,将小括号里面的东西看成一个整体,因为量词只对前一个字符有效)(多行匹配:m)(属性使用:reg.global) 一.总结 1. ...