一、vector:
1、在库中的一些表达vector底层维护了一段动态的连续空间,随着元素的不断插入,vector的内部机制会自
动检测,决定是否需要进行扩容以容纳新元素。三步操作:开辟新空间,拷贝元素,释放旧空间。
(1)构造,没有传任何参数,表示一个顺序表
explicit vector ( const Allocator& = Allocator() );
(2)构造:向顺序表中存放n个值为value的元素
explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );
(3)构造first到last一个前闭后开的区间,用区间里的元素构造一个vector
template <class InputIterator>
vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
(4)拷贝构造
vector ( const vector<T,Allocator>& x );
(5)size:返回有效元素的个数
(6)resize:第一个参数表示把当前有效元素的位置改到sz这么多,sz可能比顺序表中有效元素少,也可能比顺序表中有效元素大(a、大于size,但是小于容量,不需要改变空间,多出来的元素用c填充;b、大于容量,则需要重新开辟空间,把原空间的内容拷贝过来,多出来的进行填充,顺序表里面的指针指向新空间。)。可能进行增容,改变元素的个数。
void resize ( size_type sz, T c = T() );
(7)reserve:预留空间只改变大小,不改变元素的个数
void reserve ( size_type n );
(8)operator[]的重载:给定一个下标,访问任意空间的元素,但是不能超过有效元素的个数
reference operator[] ( size_type n );
const_reference operator[] ( size_type n ) const;
at:同operator的方法(成对的重载)
const_reference at ( size_type n ) const;
reference at ( size_type n );
(9)front:第一个元素,也是成对的重载
返回第一个元素的引用:
reference front ( );
返回const类型的引用
const_reference front ( ) const;
(10)back:
reference back ( );
const_reference back ( ) const;
注意与end区分,end返回的是size位置处的地址,和begin标记一块左闭右开的区间
(11)assign:赋值
push_back:尾插
pop_back:尾删
insert:任意位置的插入
erase:任意位置的删除
swap:交换两个顺序表中的内容
void swap ( vector<T,Allocator>& vec );
clear:清空
begin:指向第一个元素所在的位置
end:指向最后一个元素所在的位置,相当于size所在的位置
rbegin:在end的位置
rend:在begin的位置
vector里面只有尾插没有头插,但是可以使用"对象名1.insert(对象名1.begin(),0)"来代替头插。
只要能引起vector底层空间改变的东西:插入可能会增容,就可能需要给迭代器重新赋值,否则就可能会失效,(迭代器在底层关联的空间已经释放了。)。删除时可能会导致迭代器出现问题,空间存在,但是空间里的元素变成无意义的元素。
vector的使用场景:对任意位置的插入和删除操作比较少的情况。
(2)用库里面提供的vector写一段代码:
# include<assert.h>
# include<malloc.h>
# include<stdlib.h>
# include<iostream>
# include<vector>
using namespace std;
void Testvector()
{
vector<int> v1;//构造整型的v1//vector必须加标准命名空间,方法同第一篇c++博客
vector<int> v2(10, 5);//构造10个元素5
//构造一个数组(左闭右开的区间)
int arra[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
vector<int> v3(arra, arra + sizeof(arra) / sizeof(arra[0]));
cout << v3.size() << endl;
cout << v3.capacity() << endl;
//按下标的方式打印
for (size_t i = 0; i < v3.size(); ++i)
cout << v3[i] << " ";
cout << endl;
//内置类型进行打印
vector<int>::iterator it = v3.begin();
while (it != v3.end())//没有走到末尾的位置
{
cout << *it << " ";
++it;
}
cout << endl;
v3.resize(5);
cout << v3.size() << endl;
cout << v3.capacity() << endl;
for (size_t i = 0; i < v3.size(); ++i)
cout << v3[i] << " ";
v3.resize(20, 6);
cout << v3.size() << endl;
cout << v3.capacity() << endl;
for (size_t i = 0; i < v3.size(); ++i)
cout << v3[i] << " ";
}
int main()
{
Testvector();
return 0;
}
(3)自己封装一个vector:
二、用c++封装一个带头节点的双向循环链表
尾插:
尾删
头插:
# include<iostream>
# include<stdio.h>
# include<stdlib.h>
# include<string.h>
# include<assert.h>
using namespace std;
typedef int DataType;
struct ListNode
{
ListNode *_pNext;
ListNode *_pPre;
DataType _data;
//构造函数
ListNode(const DataType& data = DataType())
:_pNext(NULL)
, _pPre(NULL)
, _data(data)
{
}
};
class List
{
public:
//构造函数,构造新的链表,只有一个头节点
List()
{
_CreateHead();
}
//向链表中放n个值为data的节点
List(size_t n, const DataType& data)
{
//构造头
_CreateHead();
for (size_t i = 0; i < n; ++i)
PushBack(data);
}
//[first,last)
List(DataType *first, DataType *last)
{
_CreateHead();
while (first != last)
PushBack(*first++);
}
//拷贝构造
List(const List& l)
{
_pHead = new Node();
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
Node* pCur = L._pHead->_pNext;
while (pCur != L._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
//赋值
List& operator=(const List& s)
{
if (this != &s)
{
this->Clear();
Node* pCur = s._pHead->_pNext;
while (pCur != s._pHead)
{
this->PushBack(pCur->_data);
pCur = pCur->_pNext;
}
}
return *this;
}
//析构函数
~List()
{
Clear();//把链表中的有效元素清空,不清空头
//释放头节点
delete _pHead;
_pHead = NULL;
}
//关于容量的操作
//有效节点的个数
size_t Size()const
{
//遍历一遍链表
ListNode* pCur = _pHead->_pNext;
size_t count = 0;
//pCue朝后走,没有走到头的位置,则一圈没有结束
while (pCur != _pHead)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
//判断链表是否为空
bool Empty()const
{
return _pHead->_pNext == _pHead;
}
//
void ReSize(size_t newSize, const DataType &data = DataType())
{
int gap = newSize - Size();
if (gap > 0)//链表节点个数增多了
{
while (gap--)
PushBack(data);
}
else
{
while (gap++)
PopBack();
}
}
关于元素访问的操作
DataType& Front()
{
assert(!Empty());
return _pHead->_pNext->_data;
}
const DataType& Front()const
{
assert(!Empty());
return _pHead->_pNext->_data;
}
//最后一个节点数据
DataType& Back()
{
assert(!Empty());
return _pHead->_pPre->_data;
}
const DataType& Back()const
{
assert(!Empty());
return _pHead->_pPre->_data;
}
修改链表中的节点
//尾插
void PushBack(const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pPre = _pHead->_pPre;
pNewNode->_pNext = _pHead;
_pHead->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
}
//尾删
void PopBack()
{
if (!Empty())
return;
//标记要删除的节点
ListNode* pDelNode = _pHead->_pPre;
pDelNode->_pPre->_pNext = _pHead;
_pHead->_pPre = pDelNode->_pPre;
delete pDelNode;
}
//头插
void PushFront(const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pNext = _pHead->_pNext;
pNewNode->_pPre = _pHead;
_pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
//头删
void PopFront()
{
if (Empty())
return;
ListNode* pDelNode = _pHead->_pNext;
_pHead->_pNext = pDelNode->_pNext;
pDelNode->_pNext->_pPre = _pHead;
delete pDelNode;
}
//任意位置的插入
ListNode* Insert(ListNode* pos, const DataType& data)
{
ListNode* pNewNode = new ListNode(data);
pNewNode->_pNext = pos;
pNewNode->_pPre = pos->_pPre;
pNewNode->_pPre->_pNext = pNewNode;
//pos->_pPre = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
return pNewNode;
}
//任意位置的删除
ListNode* Erase(ListNode* pos)
{
if (NULL==pos || pos == _pHead)
return NULL;
ListNode* ret = pos->_pNext;
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete pos;
return ret;//返回删除位置的下一个位置的元素
}
void Clear()
{
ListNode* pCur = _pHead->_pNext;
while (pCur != _pHead)
{
pCur=Erase(pCur);
}
}
private:
void _CreateHead()
{
//空链表的next域和pre域都指向自己
_pHead = new ListNode;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
//打印函数
friend ostream& operator<<(ostream& _cout, const List& l)
{
ListNode *pCur = l._pHead->_pNext;
while (pCur!=l._pHead)
{
_cout << pCur->_data << " ";
pCur = pCur->_pNext;
}
return _cout;
}
private:
//指向链表的头的指针
ListNode* _pHead;
};
void TestList()
{
List l1;
List l2(10, 5);//10个元素5的链表
cout << l2<< endl;
int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List l3(array, array + sizeof(array) / sizeof(array[0]));
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
l3.ReSize(5);
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
l3.ReSize(20);
cout << l3.Size() << endl;
cout << l3 << endl;
cout << l3.Front() << endl;
cout << l3.Back() << endl;
}
int main()
{
TestList();
return 0;
}
用模板的方式实现一个双向循环链表
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<iostream>
using namespace std;
template<class T>
struct ListNode
{
ListNode(const T& data = T())
:_pPre(0)
, _pNext(0)
, _data(data)
{
}
ListNode<T>* _pPre;
ListNode<T>* _pNext;
T _data;//值域
};
//List的迭代器
template<class T,class Ref,class Ptr>
struct ListIterator
{
typedef ListNode<T> Node;
typedef Node* PNode;
typedef ListIterator<T, Ref, Ptr> Self;
public:
//构造一个空的类型
ListIterator()
:_pNode(0)
{}
//用一个节点构造
ListIterator(PNode pNode)
:_pNode(pNode)
{}
//拷贝构造,类类型对象的引用
ListIterator(const Selt& s)
:_pNode(s._pNode)
{
}
//重载
Ref operator*()
{
return _pNode->_data;
}
Ptr operator->()
{
return &(_pNode->_data);
}
Seif& operator++():
{
_pNode = _pNode->_pNext;
return *this;
}
Self operator++(int)
{
Self tmp(*this);
_pNode = _pNode->_pNext;
return tmp;
}
bool operator!=(const Self& s)
{
return _pNode != s._pNode;
}
bool operator==(const Self& s)
{
return _pNode == s._pNode;
}
private:
PNode _pNode;
};
template<class T>
class List
{
typedef ListNode<T> Node;
typedef Node* pNode;
public:
typedef ListIterator<T,T&,T*> Iterator;
public:
//构造函数
//构造空的(带头节点)
List()
{
_CreateHead();
}
//size个值为data的节点
List(size_t size, const T& data = T())
{
_CreateHead();
for (size_t i = 0; i < size; ++i)
PushBack(data);
}
//[first,last)
List(const T* first, const T* last)
{
_CreateHead();
while (first != last){
PushBack(*first);
++first;
}
}
//拷贝构造
List(const List<T>& l);
//赋值运算符的重载
List<T>& operator=(const List<T>& l);
~List()
{
Clear();
delete _pHead;
_pHead = NULL;
}
关于Iterator
Iterator Begin()
{
return _pHead->_pNext;
}
Iterator End()
{
return _pHead;
}
///关于容量capacity的
bool Empty()const
{
return _pHead->_pNext == _pHead;
}
size_t Size()const
{
pNode pCur = _pHead->_pNext;
size_t count = 0;
while (pCur != _pHead)
{
count++;
pCur = pCur->_pNext;
}
return count;
}
void Resize(size_t newSize, const T& data = T())
{
size_t oldSize = Size();
if (newSize > oldSize)
{
for (size_t i = oldSize; i < newSize; ++i)
PushBack(data);
}
else
{//有效元素个数减小了
for (size_t i = oldSize; i >= newSize; --i)
PopBack();
}
}
/元素访问access,链表不支持随机访问
T& Front()
{
return _pHead->_pNext->_data;
}
const T& Front()const
{
return _pHead->_pNext->_data;
}
T& Back()
{
return _pHead->_pNext->_data;
}
const T& Back()const
{
return _pHead->_pNext->_data;
}
modify
void PushBack(const T& data)
{
pNode pNewNode = new Node(data);
pNewNode->_pNext = _pHead;
pNewNode->_pPre = _pHead->_pPre;
pNewNode->_pPre->_pNext = pNewNode;
_pHead->_pPre = pNewNode;
}
void PopBack()
{
pNode pDelNode = _pHead->_pPre;
if (pDelNode)
{
pDelNode->_pPre->_pNext = _pHead;
_pHead->_pPre = pDelNode->_pPre;
delete pDelNode;
}
}
void PushFront(const T& data)
{
pNode pNewNode = new Node(data);
pNewNode->_pPre = _pHead;
pNewNode->_pNext = _pHead->_pNext;
_pHead->_pNext = pNewNode;
pNewNode->_pNext->_pPre = pNewNode;
}
void PopFront()
{
pNode pDelNode = _pHead->_pNext;
if (pDelNode){
pDelNode->_pNext->_pPre = _pHead;
_pHead->_pNext = pDelNode->_pNext;
delete pDelNode;
}
}
pNode Insert(pNode pos, const T& data)
{
assert(pos);
pNode pNewNode = new Node(data);
pNewNode->_pNext = pos;
pNewNode->_pPre = pos->_pPre;
pos->_pPre = pNewNode;
pNewNode->_pPre->_pNext = pNewNode;
return pNewNode;
}
pNode Erase(pNode pos)
{
assert(pos);
pNode pRet = pos->_pNext;
pos->_pPre->_pNext = pos->_pNext;
pos->_pNext->_pPre = pos->_pPre;
delete pos;
return pRet;
}
//clear清理掉当前链表的节点
void Clear()
{
pNode pDelNode = _pHead->_pNext;
//头删的方式
while (pDelNode != _pHead)
{
_pHead->_pNext = pDelNode->_pNext;
delete pDelNode;
pDelNode = _pHead->_pNext;
}
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
private:
void _CreateHead()
{
_pHead = new Node;
_pHead->_pNext = _pHead;
_pHead->_pPre = _pHead;
}
private:
ListNode<T>* _pHead;
};
void TestList()
{
List<int> l;
l.PushBack(1);
l.PushBack(2);
l.PushBack(3);
l.PushBack(4);
l.PushBack(5);
List<int>::Iterator it = l.Begin();
while (it != l.End())
{
cout << *it << " ";//it是一个节点,直接解引用是一个Node,链表的指针不能直接++,不连续。把指针进行封装
//cout << it->_data << " ";
++it;
}
}
(2)库内的实现:
A、构造函数:
a、一个有效元素都没有为空:
explicit list ( const Allocator& = Allocator() );
b、向链表中放了n个值为value的元素,
explicit list ( size_type n, const T& value = T(), const Allocator& = Allocator() );
c、用一段区间构造链表
template < class InputIterator >
list ( InputIterator first, InputIterator last, const Allocator& = Allocator() );
d、拷贝构造函数:
list ( const list<T,Allocator>& x );
B、empty:检测链表是否为空,为空为true;不为空返回false
C、返回链表中有效元素的个数
D、resize:改变链表中节点的个数,可能增多也可能减少
就不一一赘述了。
输入一个链表从尾到头打印单链表的值
法一:将链表中节点中的值全部保存在vector中,将vector逆序
#include<stdio.h>
# include<string.h>
# include<stdlib.h>
# include<iostream>
# include<vector>
using namespace std;
typedef int DataType;
typedef struct ListNode
{
ListNode *_pNext;
DataType data;
}*pListNode,ListNode;
class Solution{
public:
vector<int> PrintListFromTailToHead(pListNode *pHead)
{
vector<int> v;
ListNode *pCur = *pHead;
while (pCur){
v.push_back(pCur->data);
pCur = pCur->_pNext;
}
reverse(v.begin(), v.end());
return v;
}
};
法2:递归实现
class Solution{
public:
vector<int> PrintListFromTailToHead(ListNode *pHead)
{
vector<int> v;
_PrintListFromTailToHead(pHead, v);
return v;
}
private:
void _PrintListFromTailToHead(ListNode *pHead, vector<int> &v){
if (pHead){
_PrintListFromTailToHead(pHead->_pNext, v);
v.push_back(pHead->data);
}
}
};
法3:用栈实现
# include<stack>
class Solution{
vector<int> PrintFronTailToHead(pListNode *pHead){
vector<int> ret;
if (NULL == pHead){
return ret;
}
stack<ListNode*> s;
ListNode *pCur;
while (pCur)
{
s.push(pCur);
pCur = pCur->_pNext;
}
ret.resize(s.size());
int index = 0;
while (!s.empty()){
ret[index++] = s.top()->data;
s.pop();
}
return ret;
}
};