c++ 能够记录状态的vector

  这个想法来自于数组链表,在数组链表中,数组的每一个元素对应一个指针,这个指针是下一个元素的index。用整数表示指针。

这是这个vector的源码:

  1 #include <iostream>
  2 using std::cout;
  3
  4 template <typename T>
  5 class Vector
  6 {
  7 private:
  8     int m_block,m_size,m_asize;
  9     int *ip,*rip;//ip:actual->visual;rip:v->a
 10     T *tp;
 11     void brushrip();
 12     int partition(int,int);
 13     void qsort(int,int);
 14
 15 public:
 16     Vector(int block=100):m_block(block),m_asize(0),m_size(0),rip(NULL),ip(NULL),tp(NULL){}
 17 //    Vector(const Vector<T>& v,int block=100);
 18     int size() const{return m_size;}
 19     bool insert(const T& t,int pos=-1,int num=1);
 20     bool erase(int pos);
 21     bool erase(int pos,int num);
 22 //    bool thin();
 23     T& operator[](const int key)const;
 24     bool recover(const int const*);
 25     int* getorder() const;
 26     void sort();
 27     void swap(int pos1,int pos2);
 28 };
 29 template <typename T>
 30 void Vector<T>::swap(int pos1,int pos2)
 31 {
 32
 33     ip[rip[pos1]]=pos2;
 34     ip[rip[pos2]]=pos1;
 35     int ac1=rip[pos1],ac2=rip[pos2];
 36     rip[ip[ac1]]=ac1;
 37     rip[ip[ac2]]=ac2;
 38 }
 39
 40 template <typename T>
 41 void Vector<T>::sort()
 42 {
 43     qsort(0,m_size-1);
 44 }
 45 template <typename T>
 46 void Vector<T>::qsort(int p,int r)
 47 {
 48     if(p<r)
 49     {
 50         int q=partition(p,r);
 51         qsort(p,q-1);
 52         qsort(q+1,r);
 53     }
 54 }
 55 template <typename T>
 56 int Vector<T>::partition(int p,int r)
 57 {
 58     T& x=tp[rip[r]];
 59     int i=p-1;
 60     for(int j=p;j<=r-1;j++)
 61     {
 62         if(tp[rip[j]]<x)
 63         {
 64             i++;
 65             if(i!=j)swap(i,j);
 66         }
 67     }
 68     if(r!=i+1)swap(i+1,r);
 69     return i+1;
 70 }
 71 template <typename T>
 72 int* Vector<T>::getorder() const
 73 {
 74     if(m_size==0)return NULL;
 75     int *p=new int[m_size];
 76     for(int i=0;i<m_size;i++)p[i]=ip[i];
 77     return p;
 78 }
 79
 80 template <typename T>
 81 bool Vector<T>::recover(const int* p)
 82 {
 83 //    if((sizeof(p)/sizeof(int))<m_size)return false;
 84     for(int i=0;i<m_size && p[i]<m_size && p[i]>=0;i++)ip[i]=p[i];
 85     brushrip();
 86     return true;
 87 }
 88
 89 template <typename T>
 90 void Vector<T>::brushrip()
 91 {
 92     if(m_size==0){delete[] rip;rip=NULL;return;}
 93     if(sizeof(rip)/sizeof(int)!=m_size)
 94     {delete[] rip;rip=NULL;rip=new int[m_size];}
 95     for(int i=0;i<m_size;i++){rip[ip[i]]=i;}
 96 }
 97
 98 template <typename T>
 99 bool Vector<T>::insert(const T& t,int pos,int num)
100 {
101     if(pos<0)pos=m_size+pos+1;
102     if(pos<0 || pos>m_size)return false;
103     int newblock=(m_size+num-m_asize)/m_block+1;
104     if(newblock>0)
105     {
106         m_asize+=newblock*m_block;
107         int *ipp=new int[m_asize];
108         T *tpp=new T[m_asize];
109         for(int i=0;i<m_size;i++){tpp[i]=tp[i];ipp[i]=ip[i];}
110         delete[] tp;delete[] ip;
111         tp=tpp;ip=ipp;
112     }
113     for(int i=0;i<m_size;i++)if(ip[i]>=pos)ip[i]=ip[i]+num;
114     for(    i=0;i<num;i++)    {ip[i+m_size]=pos+i;tp[i+m_size]=t;}
115     m_size+=num;
116     brushrip();
117     return true;
118 }
119
120 template <typename T>
121 bool Vector<T>::erase(int pos)
122 {
123     if( pos<0 || pos>=m_size)return false;
124     m_size--;
125     if(rip[pos]!=m_size)
126     {
127         T temp=tp[rip[pos]];
128         tp[rip[pos]]=tp[m_size];
129         tp[m_size]=temp;
130         ip[rip[pos]]=ip[m_size];
131     }
132     for(int i=0;i<m_size;i++)if(ip[i]>pos)ip[i]--;
133     brushrip();
134     return true;
135 }
136 template <typename T>
137 bool Vector<T>::erase(int pos,int num)
138 {
139     for(int i=0;i<num;i++)if(!erase(pos))return false;
140     return true;
141 }
142
143 template <typename T>
144 T& Vector<T>::operator[](const int key)const
145 {
146     return tp[rip[key]];
147 }
148
149 int main()
150 {
151     Vector<int> v;
152     v.insert(5,0,2);
153     v.insert(6,0,8);
154     v.insert(7,4,3);
155     v.erase(3,20);
156     v.insert(10,0,2);
157     v.swap(1,2);
158     cout<<"排序前:\n";
159     for(int i=0;i<v.size();i++)cout<<v[i]<<" ";
160     int *p=v.getorder();
161     v.sort();cout<<"\n排序后:\n";
162     for(    i=0;i<v.size();i++)cout<<v[i]<<" ";
163     if(v.recover(p))cout<<"\n复原:\n";
164     for(    i=0;i<v.size();i++)cout<<v[i]<<" ";
165     cout<<"\n";
166     delete[] p;
167
168     return 0;
169 }

实现了operator[],快排,getorder,recover,insert,erase

内存的组织形式是这样的:

1.动态顺序存储,insert总将数据存储到顺序表的尾部。

2.另有有整型数组ip,与顺序表同长,建立数据存储的实际位置与表象未知的函数

3.数据交换的操作就不再直接操作数据本身,而是操作 数组ip

4.可以用getorder记录下数组ip,以后就可以用recover回复到这个状态了

也就是说,数据一旦被存储,他的实际位置就不再变了,变的只是 数组ip。而数组ip可以记录成不同的状态,所以这个vector可以用来做版本管理。

时间: 2024-10-13 18:33:18

c++ 能够记录状态的vector的相关文章

Java设计模式学习记录-状态模式

前言 状态模式是一种行为模式,用于解决系统中复杂的对象状态转换以及各个状态下的封装等问题.状态模式是将一个对象的状态从该对象中分离出来,封装到专门的状态类中,使得对象的状态可以灵活多变.这样在客户端使用时无需关心对象的状态,可以实现自身的一致性处理.最近工作有些忙,更新博客慢了.还是要严格要求自己的,抽时间也要坚持学习. 状态模式 概念介绍 状态模式允许一个对象在其状态改变时,改变它的行为,对象看起来似乎修改了它的类. 想要在改变自身状态时改变对象行为,最直接的方法就是在代码中将所有可能发生的情

最长公共子串+最长公共子序列

两道题都可以用动态规划的方法做,只是状态转移方程不同. 最长公共子串(注意子串是连续的) 1.先建立一个二维数组array[str1.size()][str2.size()](全部初始化为0),初始化第一行和第一列(元素相同处置1),然后进入状态方程 2.状态转移方程: if(str1[i] == str2[i]) array[i][j]=array[i-1][j-1]+1; (左上方对角线的值加上1) 否则无操作. 3.最后寻找整个array中的最大值即可(因为可能有多个子串) 1 /* 2

状态压缩 - LeetCode #464 Can I Win

动态规划是一种top-down求解模式,关键在于分解和求解子问题,然后根据子问题的解不断向上递推,得出最终解 因此dp涉及到保存每个计算过的子问题的解,这样当遇到同样的子问题时就不用继续向下求解而直接可以得到结果.状态压缩就是用来保存子问题的解的,主要思想是把所有可能的状态(子问题)用一个数据结构(通常是整数)统一表示,再用map把每个状态和对应结果关联起来,这样每次求解子问题时先find一下,如果map里面已经有该状态的解就不用再求了:同样每次求解完一个状态的解后也要将其放入map中保存 状态

ACM: NBUT 1646 Internet of Lights and Switches - 二进制+map+vector

NBUT 1646 Internet of Lights and Switches Time Limit:5000MS     Memory Limit:65535KB     64bit IO Format: You are a fan of "Internet of Things"(IoT, 物联网), so you build a nice Internet of Lights and Switches in your huge mansion. Formally, there

Codeforces Round #108 (Div. 2)——状态压缩DP+spfa+dfs——Garden

Vasya has a very beautiful country garden that can be represented as an n × m rectangular field divided into n·m squares. One beautiful day Vasya remembered that he needs to pave roads between k important squares that contain buildings. To pave a roa

浙大PAT CCCC L3-001 凑零钱 ( 0/1背包 &amp;&amp; 路径记录 )

题目链接 分析 : 就是一个 0/1 背包,但是需要记录具体状态的转移情况 这个可以想象成一个状态转移图,然后实际就是记录路径 将状态看成点然后转移看成边,最后输出字典序最小的路径 这里有一个很巧妙的做法 先将所有的硬币升序排序(这一点很重要) 然后在这一条件下,假设当前状态是考虑第 i 个硬币,前一个状态是考虑第 i-1 个硬币 试想对于同一个体积,如果选用的硬币数量越多是不是字典序更小 然后对于如果对于同一体积下,选用硬币数一样多的两种方案 由于我们已经升序排序,如果有一样多硬币的情况,那么

关于dp方案记录的方法思考与优化

一般的方法是记录状态是从哪儿转移来的然后递归输出. 但是明显递归有爆栈的危险. 所以可以用一个 (增加理解难度而实际没用的) 方法来避免. 具体来说,用一个vector保存答案. 例如这一题中,一般题解是用 void print(int x,int y) { if(pre[x][y]==y) { cout<<y<<" "; return; } print(x-1,pre[x][y]); cout<<y<<" ";//记

DP刷题记录

目录 dp刷题记录 codeforces 706C codeforces 940E BZOJ3997 POJ2279 GYM102082B GYM102082D codeforces132C L3-020 至多删三个字符 牛客 553C Chino with Queue POJ3260 The Fewest Coins Codeforces 372C dp刷题记录 codeforces 706C 题意:给出n个字符串,可以对每个字符串进行翻转操作, 每个操作对应一个消耗c[i],问经过操作后是否

第七篇:使用 fcntl 函数 获取,设置文件的状态标志

前言 当打开一个文件的时候,我们需要指定打开文件的模式( 只读,只写等 ).那么在程序中如何获取,修改这个文件的状态标志呢?本文将告诉你如何用 fcntl函数 获取指定文件的状态标志. 解决思路 1. 对于获取文件状态标志,我们可以通过调用fcntl函数得到一个记录文件标志的整型变量,然后分别让它和各个状态标志常量进行&操作.若操作结果为正则文件具有此状态标志,否则文件没有此状态标志.( 如果是检查只读,只写,可读可写,则需要和ACCMODE相&,然后判断其结果是否为O_RDONLY,O_