C++学习笔记(四)——栈,队列与单例模式

C++学习笔记(四)——栈,队列与单例模式

本文通过原理解释与代码实现两个方面来解释栈、队列与单例模式。

栈的原理与实现

栈是一种==“先进后出”==的数据结构,示意图如下图(图一):
在这里插入图片描述
图一就是一个栈的示意图,该栈的大小为8,现有6个元素。栈顶(_top)元素为5。对栈的操作有:

  • 初始化:创建一个空栈
  • 压栈:将一个元素放入栈中
  • 出栈:将栈顶元素拿出栈
  • 判空:判断栈是否为空
  • 清空:清空栈的所有元素
  • 查看顶元素;
  • 查看当前栈的长度;
  • 判满:判断栈是否满
    代码实现有两种方式:
  • 静态栈:核心是数组,类似于一个连续内存的数组,区别在于只能操作其顶元素
  • 静态栈:核心是链表,类似于一个不连续内存的有序存放的链表,区别在于只能操作其顶节点

静态栈的实现(C++代码)

 ///
 /// @file    Stack.cc
 /// @date    2019-02-08 21:17:08
 ///
 
#include <iostream>
using std::cout;
using std::endl;
class Stack
{
	public:
		Stack(int size)//初始化
			:_top(-1)
			 ,_size(size)
			 ,_arr(new int[_size]())
		{
			cout << "------" << endl;
		}

		bool full() //判满
		{
			return _top == _size - 1;
		}

		bool empty()  //判空
		{
			return _top == -1;
		}

		void push(const int & val)  //压栈
		{
			if(!full())
			{
				_arr[++_top] = val;
			}else
			{
				cout << "arry full" << endl;
			}
		}

		void pop()//出栈
		{
			if(!empty())
			{
				_top--;
			}else
			{
				cout << "stack empty" << endl;
			}
		}

		int top()//查看顶元素
		{
			return _arr[_top];
		}

		int arr_idx()   //查看当前栈的长度
		{
			return (_top+1);
		}
	private:
		int _top;
		int _size;
		int * _arr;
};
//main用来测试各个方法
int main(void)
{
	Stack st1(10);
	cout << "empty? " << st1.empty() << endl;
	st1.push(1);
	cout << "empty? " << st1.empty() << endl;

	for(int idx = 2; idx != 12; ++idx)
	{
		st1.push(idx);
	}
	cout << "full? " << st1.full() << endl;
	cout << "st1.arr_idx = " << st1.arr_idx() << endl;
	cout << "st1.top(): " << st1.top() << endl;
	st1.pop();
	cout << "after pop(): ";
	cout << "st1.top(): " << st1.top() << endl;
	while(!st1.empty())
	{
		cout << "top number: " << st1.top() << endl;
		st1.pop();
	}

	return 0;
}

动态栈的实现(C++代码)

动态栈与静态栈相比没有判满操作,因为动态栈对存放元素的数量没有规定。

 ///
 /// @file    linkStack.cc
 /// @date    2019-02-09 14:56:22
 ///
 
#include <iostream>
using std::cout;
using std::endl;

class Node{
	public:
		Node( Node * pnext, int num)
			:_pnext(pnext)
			 ,_num(num)
		{

		}

		Node * retNode()
		{
			return _pnext;
		}

		int num()
		{
			return _num;
		}
	private:
		Node * _pnext;
		int _num;
};

class Stack
{
	public:
//		Stack()
//			:_top(NULL)
//			,_length(0)
//		{}
		Stack(const int num)  //初始化
			:_node(new Node(NULL,num))
			,_top(_node)
			,_length(1)
		{
		}

		void push(const int num)//压栈
		{
			Node * pnode = new Node(_top,num);
			_top = pnode;
			_length++;
		}

		void pop()//出栈
		{
			if(_length > 0)
			{
				Node * temp = _top;
				_top = temp->retNode();
				delete temp;
				_length--;
			}else{
				cout << "栈已空" << endl;
			}
		}

		bool empty()
		{
			return _length;
		}

		int size()
		{
			return _length;
		}

		void clear()
		{
			while(_length)
			{
				pop();
			}
			cout << "已经清空" << endl;
		}

		int topnum()
		{
			return _top->num();
		}
	private:
		Node * _node;
		Node * _top;
		int _length;
};

int main()
{
	Stack st1(1);
	for(int idx = 2; idx < 13; idx++)
	{
		st1.push(idx);
	}
	cout << "top num: " << st1.topnum() << endl;
	cout << "st1 size: " << st1.size() << endl;

	while(st1.empty())
	{
		cout << "topnum: " << st1.topnum() << endl;
		st1.pop();
	}

	st1.push(12);
	cout << "Is empty: " << st1.empty() << endl;
	st1.clear();
	cout << "Is empty: " << st1.empty() << endl;


	return 0;
}

队列的原理与实现

队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点:

  • 队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构;

  • 在队尾添加元素,在队头删除元素;
    其结构示意图如下(图二):
    在这里插入图片描述
    队列的相关概念:

  • 队头与队尾: 允许元素插入的一端称为队尾,允许元素删除的一端称为队头;

  • 入队:队列的插入操作;

  • 出队:队列的删除操作;

队列的操作:

  • 入队: 通常命名为push()
  • 出队: 通常命名为pop()
  • 求队列中元素个数
  • 判断队列是否为空
  • 获取队首元素
    队列的分类:
  • 基于数组的循环队列(循环队列)
  • 基于链表的队列(链队列)

C++代码实现数组循环队列

 ///
 /// @file    Queue.cc
 /// @date    2019-02-08 21:53:27
 ///
 
#include <iostream>
using std::cout;
using std::endl;

class Queue
{
	public:
		Queue(int size)
			:_size(size)
			 ,_front(0)
			 ,_rear(0)
			 ,_arr(new int[_size]())
		{}
		~Queue()
		{
			delete [] _arr;
		}
		bool full() const
		{
			return (_rear%_size)-(_front%_size) == (_size -1);
		}
		bool empty() const
		{
			return (_rear%_size) == (_front%_size);
		}
		void push(const int & val)
		{
			if(!full())
			{
				_rear = _rear%_size;
				_arr[_rear++] = val;
			}else{
				cout << "queue is full" << endl;
			}
		}
		void pop()
		{
			if(!empty())
			{
				_front = _front%_size;
				_front++;
			}else{
				cout << "queue is empty " << endl;
			}
		}
		int length()
		{
			return (_rear%_size)-(_front%_size);
		}
		int & getFront()
		{
			return _arr[_front];
		}

	private:
		int _size;
		int _front;
		int _rear;
		int * _arr;
};

int main()
{
	Queue que1(6);
	for(int idx = 1; idx < 7; idx++)
	{
		que1.push(idx);
	}
	cout << "Is full? " << que1.full() << endl;
	cout << que1.getFront() << endl;
	cout << "empoty? " << que1.empty() << endl;
	while(!que1.empty())
	{
		cout << "_rear num: " << que1.getFront() << endl;
		que1.pop();
	}
	cout << "Is empty: " << que1.empty() << endl;
	return 0;
}

C++实现链表队列

 ///
 /// @file    linQueue.cc
 /// @author  XuHuanhuan(1982299154@qq.com)
 /// @date    2019-02-09 19:26:39
 ///
 
#include <iostream>
using std::cout;
using std::endl;

class Node
{
	public:
		Node(Node * front, int num)
			:_front(front)
			 ,_num(num)
		{
			
		}
	

		int retNum()
		{
			return _num;
		}

		void putFront(Node * rhs)
		{
			_front = rhs;
		}

		Node * retFront()
		{
			return _front;
		}
	private:
		Node *_front;
		int _num;
};

class Queue
{
	public:
		Queue()
		{}
		Queue(const int num)
			:_que_front(NULL)
			 ,_que_rear(NULL)
			,_que_cur(new Node(_que_front,num))
			 ,length(1)
		{
			_que_front = _que_cur;
			_que_rear = _que_cur;
		}

		void push(const int num)
		{
			_que_cur = new Node(NULL,num);
			_que_front->putFront(_que_cur);
			_que_front = _que_cur;
			 length++;
		}

		void pop()
		{
			if(length > 0)
			{
				Node * temp = _que_rear;
				_que_rear = _que_rear->retFront();
				delete temp;
				length--;
			}else{
				cout << "队列为空" << endl;
			}

		}

		bool empty()
		{
			return length;
		}

		int retNum()
		{
			return _que_rear->retNum();
		}

	private:
		Node * _que_front;
		Node * _que_rear;
		Node * _que_cur;
		int length;
};

int main()
{
	Queue que1(1);
	for(int idx = 2; idx < 13; idx++)
	{
		que1.push(idx);
	}

	while(que1.empty())
	{
		cout << "topnum: " << que1.retNum() << endl;
		que1.pop();
	}

	que1.push(12);
	cout << "Is empty: " << que1.empty() << endl;

	return 0;
}

利用Viso辅助思考可以很快的想清楚各个节点的指针该如何操作

单例模式的原理与实现

单例模式要求该类只能生成唯一的对象,所以该对象不能是栈对象,只能是堆对象。所以,单例模式在技术上就是说要创建一个类该类只能在堆中创建且只能被创建一对象
示例代码如下:

 ///
 /// @file    Singleton.cc
 /// @date    2019-02-10 14:20:54
 ///
 
#include <stdio.h>
#include <iostream>
using std::cout;
using std::endl;

class Singleton
{
public:
	static Singleton * getInstance()
	{
		if(_pInstance == NULL)   //通过static变量_pInstance的判断能够创建唯一的对象
			_pInstance = new Singleton();
		return _pInstance;
	}

private:
	Singleton(){}//将构造函数放到private中就可以避免栈对象和堆对象的创建
	
	static Singleton * _pInstance;
};

Singleton * Singleton::_pInstance = NULL;

//Singleton s3;
int main(void)
{
	//Singleton s1;//禁止该语句运行, 让其不能通过编译
	//Singleton s2;//需要在类之外调用默认构造函数
	
	//Singleton * p1 = new Singleton;
	//Singleton * p2 = new Singleton;
	Singleton * p1 = Singleton::getInstance();
	Singleton * p2 = Singleton::getInstance();
	Singleton * p3 = Singleton::getInstance();

	printf("p1 = %p\n", p1);
	printf("p2 = %p\n", p2);
	printf("p3 = %p\n", p3);

	delete p1;//不希望该语句编译通过

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值