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 http://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 http://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)。因为这在中间删除数据后会导致后面的数据向前移动,从而使效率低下。
转载请标明出处,原文地址:http://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 http://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 http://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)。因为这在中间删除数据后会导致后面的数据向前移动,从而使效率低下。
转载请标明出处,原文地址:http://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整理(http://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整理(http://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(http://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(http://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;
}
转载请标明出处,原文地址:http://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整理(http://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整理(http://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(http://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(http://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;
}
转载请标明出处,原文地址:http://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整理(http://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整理(http://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(http://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(http://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;
}
转载请标明出处,原文地址:http://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( http://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( http://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( http://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(http://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( http://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(http://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中堆操作函数的性能与《白话经典算法系列之七 堆与堆排序》一文中堆操作函数的性能是相差无几的。
转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/6967409