STL系列之一 deque双向队列
deque双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素,deque在接口上和vector非常相似,下面列出deque的常用成员函数:
deque的实现比较复杂,内部会维护一个map(注意!不是STL中的map容器)即一小块连续的空间,该空间中每个元素都是指针,指向另一段(较大的)区域,这个区域称为缓冲区,缓冲区用来保存deque中的数据。因此deque在随机访问和遍历数据会比vector慢。具体的deque实现可以参考《STL源码剖析》,当然此书中使用的SGI STL与VS2008所使用的PJ STL的实现方法还是有区别的。下面给出了deque的结构图:
由于篇幅问题,deque的实现细节就不再深入了,下面给出deque的使用范例:
- //双向队列 deque
- //by MoreWindows https://blog.csdn.net/morewindows
- #include <deque>
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- int main()
- {
- deque<int> ideq(20); //Create a deque ideq with 20 elements of default value 0
- deque<int>::iterator pos;
- int i;
-
- //使用assign()赋值 assign在计算机中就是赋值的意思
- for (i = 0; i < 20; ++i)
- ideq[i] = i;
-
- //输出deque
- printf("输出deque中数据:\n");
- for (i = 0; i < 20; ++i)
- printf("%d ", ideq[i]);
- putchar('\n');
-
- //在头尾加入新数据
- printf("\n在头尾加入新数据...\n");
- ideq.push_back(100);
- ideq.push_front(i);
-
- //输出deque
- printf("\n输出deque中数据:\n");
- for (pos = ideq.begin(); pos != ideq.end(); pos++)
- printf("%d ", *pos);
- putchar('\n');
-
- //查找
- const int FINDNUMBER = 19;
- printf("\n查找%d\n", FINDNUMBER);
- pos = find(ideq.begin(), ideq.end(), FINDNUMBER);
- if (pos != ideq.end())
- printf("find %d success\n", *pos);
- else
- printf("find failed\n");
-
- //在头尾删除数据
- printf("\n在头尾删除数据...\n");
- ideq.pop_back();
- ideq.pop_front();
-
- //输出deque
- printf("\n输出deque中数据:\n");
- for (pos = ideq.begin(); pos != ideq.end(); pos++)
- printf("%d ", *pos);
- putchar('\n');
- return 0;
- }
//双向队列 deque
//by MoreWindows https://blog.csdn.net/morewindows
#include <deque>
#include <cstdio>
#include <algorithm>
using namespace std;
int main()
{
deque<int> ideq(20); //Create a deque ideq with 20 elements of default value 0
deque<int>::iterator pos;
int i;
//使用assign()赋值 assign在计算机中就是赋值的意思
for (i = 0; i < 20; ++i)
ideq[i] = i;
//输出deque
printf("输出deque中数据:\n");
for (i = 0; i < 20; ++i)
printf("%d ", ideq[i]);
putchar('\n');
//在头尾加入新数据
printf("\n在头尾加入新数据...\n");
ideq.push_back(100);
ideq.push_front(i);
//输出deque
printf("\n输出deque中数据:\n");
for (pos = ideq.begin(); pos != ideq.end(); pos++)
printf("%d ", *pos);
putchar('\n');
//查找
const int FINDNUMBER = 19;
printf("\n查找%d\n", FINDNUMBER);
pos = find(ideq.begin(), ideq.end(), FINDNUMBER);
if (pos != ideq.end())
printf("find %d success\n", *pos);
else
printf("find failed\n");
//在头尾删除数据
printf("\n在头尾删除数据...\n");
ideq.pop_back();
ideq.pop_front();
//输出deque
printf("\n输出deque中数据:\n");
for (pos = ideq.begin(); pos != ideq.end(); pos++)
printf("%d ", *pos);
putchar('\n');
return 0;
}
运行结果如下:
另外要注意一点。对于deque和vector来说,尽量少用erase(pos)和erase(beg,end)。因为这在中间删除数据后会导致后面的数据向前移动,从而使效率低下。
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6946811
STL系列之一 deque双向队列
deque双向队列是一种双向开口的连续线性空间,可以高效的在头尾两端插入和删除元素,deque在接口上和vector非常相似,下面列出deque的常用成员函数:
deque的实现比较复杂,内部会维护一个map(注意!不是STL中的map容器)即一小块连续的空间,该空间中每个元素都是指针,指向另一段(较大的)区域,这个区域称为缓冲区,缓冲区用来保存deque中的数据。因此deque在随机访问和遍历数据会比vector慢。具体的deque实现可以参考《STL源码剖析》,当然此书中使用的SGI STL与VS2008所使用的PJ STL的实现方法还是有区别的。下面给出了deque的结构图:
由于篇幅问题,deque的实现细节就不再深入了,下面给出deque的使用范例:
- //双向队列 deque
- //by MoreWindows https://blog.csdn.net/morewindows
- #include <deque>
- #include <cstdio>
- #include <algorithm>
- using namespace std;
- int main()
- {
- deque<int> ideq(20); //Create a deque ideq with 20 elements of default value 0
- deque<int>::iterator pos;
- int i;
- //使用assign()赋值 assign在计算机中就是赋值的意思
- for (i = 0; i < 20; ++i)
- ideq[i] = i;
- //输出deque
- printf("输出deque中数据:\n");
- for (i = 0; i < 20; ++i)
- printf("%d ", ideq[i]);
- putchar('\n');
- //在头尾加入新数据
- printf("\n在头尾加入新数据...\n");
- ideq.push_back(100);
- ideq.push_front(i);
- //输出deque
- printf("\n输出deque中数据:\n");
- for (pos = ideq.begin(); pos != ideq.end(); pos++)
- printf("%d ", *pos);
- putchar('\n');
- //查找
- const int FINDNUMBER = 19;
- printf("\n查找%d\n", FINDNUMBER);
- pos = find(ideq.begin(), ideq.end(), FINDNUMBER);
- if (pos != ideq.end())
- printf("find %d success\n", *pos);
- else
- printf("find failed\n");
- //在头尾删除数据
- printf("\n在头尾删除数据...\n");
- ideq.pop_back();
- ideq.pop_front();
- //输出deque
- printf("\n输出deque中数据:\n");
- for (pos = ideq.begin(); pos != ideq.end(); pos++)
- printf("%d ", *pos);
- putchar('\n');
- return 0;
- }
//双向队列 deque //by MoreWindows https://blog.csdn.net/morewindows #include <deque> #include <cstdio> #include <algorithm> using namespace std; int main() { deque<int> ideq(20); //Create a deque ideq with 20 elements of default value 0 deque<int>::iterator pos; int i; //使用assign()赋值 assign在计算机中就是赋值的意思 for (i = 0; i < 20; ++i) ideq[i] = i; //输出deque printf("输出deque中数据:\n"); for (i = 0; i < 20; ++i) printf("%d ", ideq[i]); putchar('\n'); //在头尾加入新数据 printf("\n在头尾加入新数据...\n"); ideq.push_back(100); ideq.push_front(i); //输出deque printf("\n输出deque中数据:\n"); for (pos = ideq.begin(); pos != ideq.end(); pos++) printf("%d ", *pos); putchar('\n'); //查找 const int FINDNUMBER = 19; printf("\n查找%d\n", FINDNUMBER); pos = find(ideq.begin(), ideq.end(), FINDNUMBER); if (pos != ideq.end()) printf("find %d success\n", *pos); else printf("find failed\n"); //在头尾删除数据 printf("\n在头尾删除数据...\n"); ideq.pop_back(); ideq.pop_front(); //输出deque printf("\n输出deque中数据:\n"); for (pos = ideq.begin(); pos != ideq.end(); pos++) printf("%d ", *pos); putchar('\n'); return 0; }
运行结果如下:
另外要注意一点。对于deque和vector来说,尽量少用erase(pos)和erase(beg,end)。因为这在中间删除数据后会导致后面的数据向前移动,从而使效率低下。
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6946811
STL系列之三 queue 单向队列
queue单向队列与栈有点类似,一个是在同一端存取数据,另一个是在一端存入数据,另一端取出数据。单向队列中的数据是先进先出(First In First Out,FIFO)。在STL中,单向队列也是以别的容器作为底部结构,再将接口改变,使之符合单向队列的特性就可以了。因此实现也是非常方便的。下面就给出单向队列的函数列表和VS2008中单向队列的源代码。单向队列一共6个常用函数(front()、back()、push()、pop()、empty()、size()),与栈的常用函数较为相似。
STL系列之二 stack栈
栈(statck)这种数据结构在计算机中是相当出名的。栈中的数据是先进后出的(First In Last Out, FILO)。栈只有一个出口,允许新增元素(只能在栈顶上增加)、移出元素(只能移出栈顶元素)、取得栈顶元素等操作。在STL中,栈是以别的容器作为底部结构,再将接口改变,使之符合栈的特性就可以了。因此实现非常的方便。下面就给出栈的函数列表和VS2008中栈的源代码,在STL中栈一共就5个常用操作函数(top()、push()、pop()、
size()、empty() ),很好记的。
VS2008中栈的源代码
友情提示:初次阅读时请注意其实现思想,不要在细节上浪费过多的时间。
- //VS2008中 stack的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows)
- template<class _Ty, class _Container = deque<_Ty> >
- class stack
- { // LIFO queue implemented with a container
- public:
- typedef _Container container_type;
- typedef typename _Container::value_type value_type;
- typedef typename _Container::size_type size_type;
- typedef typename _Container::reference reference;
- typedef typename _Container::const_reference const_reference;
-
- stack() : c()
- { // construct with empty container
- }
-
- explicit stack(const _Container& _Cont) : c(_Cont)
- { // construct by copying specified container
- }
-
- bool empty() const
- { // test if stack is empty
- return (c.empty());
- }
-
- size_type size() const
- { // test length of stack
- return (c.size());
- }
-
- reference top()
- { // return last element of mutable stack
- return (c.back());
- }
-
- const_reference top() const
- { // return last element of nonmutable stack
- return (c.back());
- }
-
- void push(const value_type& _Val)
- { // insert element at end
- c.push_back(_Val);
- }
-
- void pop()
- { // erase last element
- c.pop_back();
- }
-
- const _Container& _Get_container() const
- { // get reference to container
- return (c);
- }
-
- protected:
- _Container c; // the underlying container
- };
//VS2008中 stack的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows)
template<class _Ty, class _Container = deque<_Ty> >
class stack
{ // LIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
stack() : c()
{ // construct with empty container
}
explicit stack(const _Container& _Cont) : c(_Cont)
{ // construct by copying specified container
}
bool empty() const
{ // test if stack is empty
return (c.empty());
}
size_type size() const
{ // test length of stack
return (c.size());
}
reference top()
{ // return last element of mutable stack
return (c.back());
}
const_reference top() const
{ // return last element of nonmutable stack
return (c.back());
}
void push(const value_type& _Val)
{ // insert element at end
c.push_back(_Val);
}
void pop()
{ // erase last element
c.pop_back();
}
const _Container& _Get_container() const
{ // get reference to container
return (c);
}
protected:
_Container c; // the underlying container
};
可以看出,由于栈只是进一步封装别的数据结构,并提供自己的接口,所以代码非常简洁,如果不指定容器,默认是用deque来作为其底层数据结构的(对deque不是很了解?可以参阅《STL系列之一
deque双向队列》)。下面给出栈的使用范例:
- //栈 stack支持 empty() size() top() push() pop()
- // by MoreWindows(https://blog.csdn.net/MoreWindows)
- #include <stack>
- #include <vector>
- #include <list>
- #include <cstdio>
- using namespace std;
- int main()
- {
- //可以使用list或vector作为栈的容器,默认是使用deque的。
- stack<int, list<int>> a;
- stack<int, vector<int>> b;
- int i;
-
- //压入数据
- for (i = 0; i < 10; i++)
- {
- a.push(i);
- b.push(i);
- }
-
- //栈的大小
- printf("%d %d\n", a.size(), b.size());
-
- //取栈项数据并将数据弹出栈
- while (!a.empty())
- {
- printf("%d ", a.top());
- a.pop();
- }
- putchar('\n');
-
- while (!b.empty())
- {
- printf("%d ", b.top());
- b.pop();
- }
- putchar('\n');
- return 0;
- }
//栈 stack支持 empty() size() top() push() pop()
// by MoreWindows(https://blog.csdn.net/MoreWindows)
#include <stack>
#include <vector>
#include <list>
#include <cstdio>
using namespace std;
int main()
{
//可以使用list或vector作为栈的容器,默认是使用deque的。
stack<int, list<int>> a;
stack<int, vector<int>> b;
int i;
//压入数据
for (i = 0; i < 10; i++)
{
a.push(i);
b.push(i);
}
//栈的大小
printf("%d %d\n", a.size(), b.size());
//取栈项数据并将数据弹出栈
while (!a.empty())
{
printf("%d ", a.top());
a.pop();
}
putchar('\n');
while (!b.empty())
{
printf("%d ", b.top());
b.pop();
}
putchar('\n');
return 0;
}
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6950881
STL系列之二 stack栈
栈(statck)这种数据结构在计算机中是相当出名的。栈中的数据是先进后出的(First In Last Out, FILO)。栈只有一个出口,允许新增元素(只能在栈顶上增加)、移出元素(只能移出栈顶元素)、取得栈顶元素等操作。在STL中,栈是以别的容器作为底部结构,再将接口改变,使之符合栈的特性就可以了。因此实现非常的方便。下面就给出栈的函数列表和VS2008中栈的源代码,在STL中栈一共就5个常用操作函数(top()、push()、pop()、 size()、empty() ),很好记的。
VS2008中栈的源代码
友情提示:初次阅读时请注意其实现思想,不要在细节上浪费过多的时间。
- //VS2008中 stack的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows)
- template<class _Ty, class _Container = deque<_Ty> >
- class stack
- { // LIFO queue implemented with a container
- public:
- typedef _Container container_type;
- typedef typename _Container::value_type value_type;
- typedef typename _Container::size_type size_type;
- typedef typename _Container::reference reference;
- typedef typename _Container::const_reference const_reference;
- stack() : c()
- { // construct with empty container
- }
- explicit stack(const _Container& _Cont) : c(_Cont)
- { // construct by copying specified container
- }
- bool empty() const
- { // test if stack is empty
- return (c.empty());
- }
- size_type size() const
- { // test length of stack
- return (c.size());
- }
- reference top()
- { // return last element of mutable stack
- return (c.back());
- }
- const_reference top() const
- { // return last element of nonmutable stack
- return (c.back());
- }
- void push(const value_type& _Val)
- { // insert element at end
- c.push_back(_Val);
- }
- void pop()
- { // erase last element
- c.pop_back();
- }
- const _Container& _Get_container() const
- { // get reference to container
- return (c);
- }
- protected:
- _Container c; // the underlying container
- };
//VS2008中 stack的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows) template<class _Ty, class _Container = deque<_Ty> > class stack { // LIFO queue implemented with a container public: typedef _Container container_type; typedef typename _Container::value_type value_type; typedef typename _Container::size_type size_type; typedef typename _Container::reference reference; typedef typename _Container::const_reference const_reference; stack() : c() { // construct with empty container } explicit stack(const _Container& _Cont) : c(_Cont) { // construct by copying specified container } bool empty() const { // test if stack is empty return (c.empty()); } size_type size() const { // test length of stack return (c.size()); } reference top() { // return last element of mutable stack return (c.back()); } const_reference top() const { // return last element of nonmutable stack return (c.back()); } void push(const value_type& _Val) { // insert element at end c.push_back(_Val); } void pop() { // erase last element c.pop_back(); } const _Container& _Get_container() const { // get reference to container return (c); } protected: _Container c; // the underlying container };
可以看出,由于栈只是进一步封装别的数据结构,并提供自己的接口,所以代码非常简洁,如果不指定容器,默认是用deque来作为其底层数据结构的(对deque不是很了解?可以参阅《STL系列之一 deque双向队列》)。下面给出栈的使用范例:
- //栈 stack支持 empty() size() top() push() pop()
- // by MoreWindows(https://blog.csdn.net/MoreWindows)
- #include <stack>
- #include <vector>
- #include <list>
- #include <cstdio>
- using namespace std;
- int main()
- {
- //可以使用list或vector作为栈的容器,默认是使用deque的。
- stack<int, list<int>> a;
- stack<int, vector<int>> b;
- int i;
- //压入数据
- for (i = 0; i < 10; i++)
- {
- a.push(i);
- b.push(i);
- }
- //栈的大小
- printf("%d %d\n", a.size(), b.size());
- //取栈项数据并将数据弹出栈
- while (!a.empty())
- {
- printf("%d ", a.top());
- a.pop();
- }
- putchar('\n');
- while (!b.empty())
- {
- printf("%d ", b.top());
- b.pop();
- }
- putchar('\n');
- return 0;
- }
//栈 stack支持 empty() size() top() push() pop() // by MoreWindows(https://blog.csdn.net/MoreWindows) #include <stack> #include <vector> #include <list> #include <cstdio> using namespace std; int main() { //可以使用list或vector作为栈的容器,默认是使用deque的。 stack<int, list<int>> a; stack<int, vector<int>> b; int i; //压入数据 for (i = 0; i < 10; i++) { a.push(i); b.push(i); } //栈的大小 printf("%d %d\n", a.size(), b.size()); //取栈项数据并将数据弹出栈 while (!a.empty()) { printf("%d ", a.top()); a.pop(); } putchar('\n'); while (!b.empty()) { printf("%d ", b.top()); b.pop(); } putchar('\n'); return 0; }
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6950881
STL系列之三 queue 单向队列
queue单向队列与栈有点类似,一个是在同一端存取数据,另一个是在一端存入数据,另一端取出数据。单向队列中的数据是先进先出(First In First Out,FIFO)。在STL中,单向队列也是以别的容器作为底部结构,再将接口改变,使之符合单向队列的特性就可以了。因此实现也是非常方便的。下面就给出单向队列的函数列表和VS2008中单向队列的源代码。单向队列一共6个常用函数(front()、back()、push()、pop()、empty()、size()),与栈的常用函数较为相似。
VS2008中queue单向队列的源代码
友情提示:初次阅读时请注意其实现思想,不要在细节上浪费过多的时间。
- <SPAN style="FONT-SIZE: 18px">//VS2008中 queue的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows)
- template<class _Ty, class _Container = deque<_Ty> >
- class queue
- { // FIFO queue implemented with a container
- public:
- typedef _Container container_type;
- typedef typename _Container::value_type value_type;
- typedef typename _Container::size_type size_type;
- typedef typename _Container::reference reference;
- typedef typename _Container::const_reference const_reference;
- queue() : c()
- { // construct with empty container
- }
- explicit queue(const _Container& _Cont) : c(_Cont)
- { // construct by copying specified container
- }
- bool empty() const
- { // test if queue is empty
- return (c.empty());
- }
- size_type size() const
- { // return length of queue
- return (c.size());
- }
- reference front()
- { // return first element of mutable queue
- return (c.front());
- }
- const_reference front() const
- { // return first element of nonmutable queue
- return (c.front());
- }
- reference back()
- { // return last element of mutable queue
- return (c.back());
- }
- const_reference back() const
- { // return last element of nonmutable queue
- return (c.back());
- }
- void push(const value_type& _Val)
- { // insert element at beginning
- c.push_back(_Val);
- }
- void pop()
- { // erase element at end
- c.pop_front();
- }
- const _Container& _Get_container() const
- { // get reference to container
- return (c);
- }
- protected:
- _Container c; // the underlying container
- };</SPAN>
//VS2008中 queue的定义 MoreWindows整理(https://blog.csdn.net/MoreWindows)
template<class _Ty, class _Container = deque<_Ty> >
class queue
{ // FIFO queue implemented with a container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
queue() : c()
{ // construct with empty container
}
explicit queue(const _Container& _Cont) : c(_Cont)
{ // construct by copying specified container
}
bool empty() const
{ // test if queue is empty
return (c.empty());
}
size_type size() const
{ // return length of queue
return (c.size());
}
reference front()
{ // return first element of mutable queue
return (c.front());
}
const_reference front() const
{ // return first element of nonmutable queue
return (c.front());
}
reference back()
{ // return last element of mutable queue
return (c.back());
}
const_reference back() const
{ // return last element of nonmutable queue
return (c.back());
}
void push(const value_type& _Val)
{ // insert element at beginning
c.push_back(_Val);
}
void pop()
{ // erase element at end
c.pop_front();
}
const _Container& _Get_container() const
{ // get reference to container
return (c);
}
protected:
_Container c; // the underlying container
};
可以看出,由于queue只是进一步封装别的数据结构,并提供自己的接口,所以代码非常简洁,如果不指定容器,默认是用deque来作为其底层数据结构的(对deque不是很了解?可以参阅《STL系列之一deque双向队列》)。下面给出单向队列的使用范例:
- //单向队列 queue支持 empty() size() front() back() push() pop()
- //By MoreWindows(https://blog.csdn.net/MoreWindows)
- #include <queue>
- #include <vector>
- #include <list>
- #include <cstdio>
- using namespace std;
- int main()
- {
- //可以使用list作为单向队列的容器,默认是使用deque的。
- queue<int, list<int>> a;
- queue<int> b;
- int i;
- //压入数据
- for (i = 0; i < 10; i++)
- {
- a.push(i);
- b.push(i);
- }
- //单向队列的大小
- printf("%d %d\n", a.size(), b.size());
- //队列头和队列尾
- printf("%d %d\n", a.front(), a.back());
- printf("%d %d\n", b.front(), b.back());
- //取单向队列项数据并将数据移出单向队列
- while (!a.empty())
- {
- printf("%d ", a.front());
- a.pop();
- }
- putchar('\n');
- while (!b.empty())
- {
- printf("%d ", b.front());
- b.pop();
- }
- putchar('\n');
- return 0;
- }
//单向队列 queue支持 empty() size() front() back() push() pop() //By MoreWindows(https://blog.csdn.net/MoreWindows) #include <queue> #include <vector> #include <list> #include <cstdio> using namespace std; int main() { //可以使用list作为单向队列的容器,默认是使用deque的。 queue<int, list<int>> a; queue<int> b; int i; //压入数据 for (i = 0; i < 10; i++) { a.push(i); b.push(i); } //单向队列的大小 printf("%d %d\n", a.size(), b.size()); //队列头和队列尾 printf("%d %d\n", a.front(), a.back()); printf("%d %d\n", b.front(), b.back()); //取单向队列项数据并将数据移出单向队列 while (!a.empty()) { printf("%d ", a.front()); a.pop(); } putchar('\n'); while (!b.empty()) { printf("%d ", b.front()); b.pop(); } putchar('\n'); return 0; }
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6950917
STL系列之四 heap 堆
下面再介绍STL中与堆相关的4个函数——建立堆make_heap(),在堆中添加数据push_heap(),在堆中删除数据pop_heap()和堆排序sort_heap():
头文件 #include <algorithm>
下面的_First与_Last为可以随机访问的迭代器(指针),_Comp为比较函数(仿函数),其规则——如果函数的第一个参数小于第二个参数应返回true,否则返回false。
建立堆
make_heap(_First, _Last, _Comp)
默认是建立最大堆的。对int类型,可以在第三个参数传入greater<int>()得到最小堆。
在堆中添加数据
push_heap (_First, _Last)
要先在容器中加入数据,再调用push_heap ()
在堆中删除数据
pop_heap(_First, _Last)
要先调用pop_heap()再在容器中删除数据
堆排序
sort_heap(_First, _Last)
排序之后就不再是一个合法的heap了
有关堆与堆排序的更详细介绍请参阅——《白话经典算法系列之七 堆与堆排序》
下面给出STL中heap相关函数的使用范例:
- //by MoreWindows( https://blog.csdn.net/MoreWindows )
- #include <cstdio>
- #include <vector>
- #include <algorithm>
- #include <functional>
- using namespace std;
- void PrintfVectorInt(vector<int> &vet)
- {
- for (vector<int>::iterator pos = vet.begin(); pos != vet.end(); pos++)
- printf("%d ", *pos);
- putchar('\n');
- }
- int main()
- {
- const int MAXN = 20;
- int a[MAXN];
- int i;
- for (i = 0; i < MAXN; ++i)
- a[i] = rand() % (MAXN * 2);
- //动态申请vector 并对vector建堆
- vector<int> *pvet = new vector<int>(40);
- pvet->assign(a, a + MAXN);
- //建堆
- make_heap(pvet->begin(), pvet->end());
- PrintfVectorInt(*pvet);
- //加入新数据 先在容器中加入,再调用push_heap()
- pvet->push_back(25);
- push_heap(pvet->begin(), pvet->end());
- PrintfVectorInt(*pvet);
- //删除数据 要先调用pop_heap(),再在容器中删除
- pop_heap(pvet->begin(), pvet->end());
- pvet->pop_back();
- pop_heap(pvet->begin(), pvet->end());
- pvet->pop_back();
- PrintfVectorInt(*pvet);
- //堆排序
- sort_heap(pvet->begin(), pvet->end());
- PrintfVectorInt(*pvet);
- delete pvet;
- return 0;
- }
//by MoreWindows( https://blog.csdn.net/MoreWindows ) #include <cstdio> #include <vector> #include <algorithm> #include <functional> using namespace std; void PrintfVectorInt(vector<int> &vet) { for (vector<int>::iterator pos = vet.begin(); pos != vet.end(); pos++) printf("%d ", *pos); putchar('\n'); } int main() { const int MAXN = 20; int a[MAXN]; int i; for (i = 0; i < MAXN; ++i) a[i] = rand() % (MAXN * 2); //动态申请vector 并对vector建堆 vector<int> *pvet = new vector<int>(40); pvet->assign(a, a + MAXN); //建堆 make_heap(pvet->begin(), pvet->end()); PrintfVectorInt(*pvet); //加入新数据 先在容器中加入,再调用push_heap() pvet->push_back(25); push_heap(pvet->begin(), pvet->end()); PrintfVectorInt(*pvet); //删除数据 要先调用pop_heap(),再在容器中删除 pop_heap(pvet->begin(), pvet->end()); pvet->pop_back(); pop_heap(pvet->begin(), pvet->end()); pvet->pop_back(); PrintfVectorInt(*pvet); //堆排序 sort_heap(pvet->begin(), pvet->end()); PrintfVectorInt(*pvet); delete pvet; return 0; }
掌握其基本用法后,我们用这个堆排序和《白话经典算法系列》中的堆排序、快速排序,归并排序来进行个性能测试(Win7 + VS2008 Release下),测试代码如下:
- // by MoreWindows( https://blog.csdn.net/MoreWindows )
- #include <cstdio>
- #include <algorithm>
- #include <ctime>
- using namespace std;
- //------------------------快速排序----------------------------
- void quick_sort(int s[], int l, int r)
- {
- if (l < r)
- {
- int i = l, j = r, x = s[l];
- while (i < j)
- {
- while(i < j && s[j] >= x) // 从右向左找第一个小于x的数
- j--;
- if(i < j)
- s[i++] = s[j];
- while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数
- i++;
- if(i < j)
- s[j--] = s[i];
- }
- s[i] = x;
- quick_sort(s, l, i - 1); // 递归调用
- quick_sort(s, i + 1, r);
- }
- }
- //------------------------归并排序----------------------------
- //将有二个有序数列a[first...mid]和a[mid...last]合并。
- void mergearray(int a[], int first, int mid, int last, int temp[])
- {
- int i = first, j = mid + 1;
- int m = mid, n = last;
- int k = 0;
- while (i <= m && j <= n)
- {
- if (a[i] < a[j])
- temp[k++] = a[i++];
- else
- temp[k++] = a[j++];
- }
- while (i <= m)
- temp[k++] = a[i++];
- while (j <= n)
- temp[k++] = a[j++];
- for (i = 0; i < k; i++)
- a[first + i] = temp[i];
- }
- void mergesort(int a[], int first, int last, int temp[])
- {
- if (first < last)
- {
- int mid = (first + last) / 2;
- mergesort(a, first, mid, temp); //左边有序
- mergesort(a, mid + 1, last, temp); //右边有序
- mergearray(a, first, mid, last, temp); //再将二个有序数列合并
- }
- }
- bool MergeSort(int a[], int n)
- {
- int *p = new int[n];
- if (p == NULL)
- return false;
- mergesort(a, 0, n - 1, p);
- return true;
- }
- //------------------------堆排序---------------------------
- inline void Swap(int &a, int &b)
- {
- int c = a;
- a = b;
- b = c;
- }
- //建立最小堆
- // 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2
- void MinHeapFixdown(int a[], int i, int n)
- {
- int j, temp;
- temp = a[i];
- j = 2 * i + 1;
- while (j < n)
- {
- if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的
- j++;
- if (a[j] >= temp)
- break;
- a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点
- i = j;
- j = 2 * i + 1;
- }
- a[i] = temp;
- }
- //建立最小堆
- void MakeMinHeap(int a[], int n)
- {
- for (int i = n / 2 - 1; i >= 0; i--)
- MinHeapFixdown(a, i, n);
- }
- void MinheapsortTodescendarray(int a[], int n)
- {
- for (int i = n - 1; i >= 1; i--)
- {
- Swap(a[i], a[0]);
- MinHeapFixdown(a, 0, i);
- }
- }
- const int MAXN = 5000000;
- int a[MAXN];
- int b[MAXN], c[MAXN], d[MAXN];
- int main()
- {
- int i;
- srand(time(NULL));
- for (i = 0; i < MAXN; ++i)
- a[i] = rand() * rand(); //注rand()产生的数在0到0x7FFF之间
- for (i = 0; i < MAXN; ++i)
- d[i] = c[i] = b[i] = a[i];
- clock_t ibegin, iend;
- printf("--当前数据量为%d--By MoreWindows(https://blog.csdn.net/MoreWindows)--\n", MAXN);
- //快速排序
- printf("快速排序: ");
- ibegin = clock();
- quick_sort(a, 0, MAXN - 1);
- iend = clock();
- printf("%d毫秒\n", iend - ibegin);
- //归并排序
- printf("归并排序: ");
- ibegin = clock();
- MergeSort(b, MAXN);
- iend = clock();
- printf("%d毫秒\n", iend - ibegin);
- //堆排序
- printf("堆排序: ");
- ibegin = clock();
- MakeMinHeap(c, MAXN);
- MinheapsortTodescendarray(c, MAXN);
- iend = clock();
- printf("%d毫秒\n", iend - ibegin);
- //STL中的堆排序
- printf("STL中的堆排序: ");
- ibegin = clock();
- make_heap(d, d + MAXN);
- sort_heap(d, d + MAXN);
- iend = clock();
- printf("%d毫秒\n", iend - ibegin);
- return 0;
- }
// by MoreWindows( https://blog.csdn.net/MoreWindows ) #include <cstdio> #include <algorithm> #include <ctime> using namespace std; //------------------------快速排序---------------------------- void quick_sort(int s[], int l, int r) { if (l < r) { int i = l, j = r, x = s[l]; while (i < j) { while(i < j && s[j] >= x) // 从右向左找第一个小于x的数 j--; if(i < j) s[i++] = s[j]; while(i < j && s[i] < x) // 从左向右找第一个大于等于x的数 i++; if(i < j) s[j--] = s[i]; } s[i] = x; quick_sort(s, l, i - 1); // 递归调用 quick_sort(s, i + 1, r); } } //------------------------归并排序---------------------------- //将有二个有序数列a[first...mid]和a[mid...last]合并。 void mergearray(int a[], int first, int mid, int last, int temp[]) { int i = first, j = mid + 1; int m = mid, n = last; int k = 0; while (i <= m && j <= n) { if (a[i] < a[j]) temp[k++] = a[i++]; else temp[k++] = a[j++]; } while (i <= m) temp[k++] = a[i++]; while (j <= n) temp[k++] = a[j++]; for (i = 0; i < k; i++) a[first + i] = temp[i]; } void mergesort(int a[], int first, int last, int temp[]) { if (first < last) { int mid = (first + last) / 2; mergesort(a, first, mid, temp); //左边有序 mergesort(a, mid + 1, last, temp); //右边有序 mergearray(a, first, mid, last, temp); //再将二个有序数列合并 } } bool MergeSort(int a[], int n) { int *p = new int[n]; if (p == NULL) return false; mergesort(a, 0, n - 1, p); return true; } //------------------------堆排序--------------------------- inline void Swap(int &a, int &b) { int c = a; a = b; b = c; } //建立最小堆 // 从i节点开始调整,n为节点总数 从0开始计算 i节点的子节点为 2*i+1, 2*i+2 void MinHeapFixdown(int a[], int i, int n) { int j, temp; temp = a[i]; j = 2 * i + 1; while (j < n) { if (j + 1 < n && a[j + 1] < a[j]) //在左右孩子中找最小的 j++; if (a[j] >= temp) break; a[i] = a[j]; //把较小的子结点往上移动,替换它的父结点 i = j; j = 2 * i + 1; } a[i] = temp; } //建立最小堆 void MakeMinHeap(int a[], int n) { for (int i = n / 2 - 1; i >= 0; i--) MinHeapFixdown(a, i, n); } void MinheapsortTodescendarray(int a[], int n) { for (int i = n - 1; i >= 1; i--) { Swap(a[i], a[0]); MinHeapFixdown(a, 0, i); } } const int MAXN = 5000000; int a[MAXN]; int b[MAXN], c[MAXN], d[MAXN]; int main() { int i; srand(time(NULL)); for (i = 0; i < MAXN; ++i) a[i] = rand() * rand(); //注rand()产生的数在0到0x7FFF之间 for (i = 0; i < MAXN; ++i) d[i] = c[i] = b[i] = a[i]; clock_t ibegin, iend; printf("--当前数据量为%d--By MoreWindows(https://blog.csdn.net/MoreWindows)--\n", MAXN); //快速排序 printf("快速排序: "); ibegin = clock(); quick_sort(a, 0, MAXN - 1); iend = clock(); printf("%d毫秒\n", iend - ibegin); //归并排序 printf("归并排序: "); ibegin = clock(); MergeSort(b, MAXN); iend = clock(); printf("%d毫秒\n", iend - ibegin); //堆排序 printf("堆排序: "); ibegin = clock(); MakeMinHeap(c, MAXN); MinheapsortTodescendarray(c, MAXN); iend = clock(); printf("%d毫秒\n", iend - ibegin); //STL中的堆排序 printf("STL中的堆排序: "); ibegin = clock(); make_heap(d, d + MAXN); sort_heap(d, d + MAXN); iend = clock(); printf("%d毫秒\n", iend - ibegin); return 0; }
对100000(十万)个数据的测试结果:
对500000(五十万)个数据的测试结果:
对1000000(一百万)个数据的测试结果:
对5000000(五百万)个数据的测试结果:
从中可以看出快速排序的效率确实要比其它同为O(N * logN)的排序算法要高,而STL中堆操作函数的性能与《白话经典算法系列之七 堆与堆排序》一文中堆操作函数的性能是相差无几的。
转载请标明出处,原文地址:https://blog.csdn.net/morewindows/article/details/6967409