堆栈是一个后进先出(last-in-first-out, LIFO)的数据结构。
1. 数组实现的堆栈
源代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template< class T>
class Stack{
public:
Stack( int MaxStackSize= 10);
~Stack(){
delete [] stack;
}
bool IsEmpty() const{
return top==- 1;
}
bool IsFull() const{
return top==MaxTop;
}
T Top() const;
Stack<T>& Add( const T& x);
Stack<T>& Delete(T & x);
private:
int top;
int MaxTop;
T* stack;
};
template< class T>
Stack<T>::Stack( int MaxStackSize)
{
MaxTop=MaxStackSize- 1;
stack= new T[MaxStackSize];
top=- 1;
}
template< class T>
T Stack<T>::Top() const
{
if(IsEmpty())
throw " Out of Bounds ";
return stack[top];
}
template< class T>
Stack<T>& Stack<T>::Add( const T& x)
{
if(IsFull())
throw " Not enough Memorry ";
stack[++top]=x;
cout<< " Success "<<endl;
return * this;
}
template< class T>
Stack<T>& Stack<T>::Delete(T & x)
{
if(IsEmpty())
throw " Out of Bounds ";
x=stack[top--];
return * this;
}
int main( void)
{
int x;
Stack< int> S( 3);
try {
S.Add( 1).Add( 2).Add( 3).Add( 4);
}
catch (...) {
cout << " Could not complete additions " << endl;
}
cout << " Stack should be 123 " << endl;
cout << " Stack top is " << S.Top() << endl;
try {
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
}
catch (...) {
cout << " Last delete failed " << endl;
}
}
源代码如下:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template< class T>
class LinkedStack;
template< class T>
class Node{
friend class LinkedStack<T>;
private:
T data;
Node<T>* link;
};
template< class T>
class LinkedStack{
public:
LinkedStack(){
top= 0;
}
~LinkedStack();
bool IsEmpty() const{
return top== 0;
}
bool IsFull() const;
T Top() const;
LinkedStack<T>& Add( const T& x);
LinkedStack<T>& Delete(T& x);
private:
Node<T>*top;
};
template< class T>
LinkedStack<T>::~LinkedStack()
{
Node<T>*next;
while(top){
next=top->link;
delete top;
top=next;
}
}
template< class T>
bool LinkedStack<T>::IsFull() const
{
try{
Node<T> *p= new Node<T>;
delete p;
return false;
}
catch(...){
return true;
}
}
template< class T>
T LinkedStack<T>::Top() const
{
if(IsEmpty())
throw " OutofBounds ";
return top->data;
}
template< class T>
LinkedStack<T>& LinkedStack<T>::Add( const T& x)
{
Node<T> *p= new Node<T>;
p->data=x;
p->link=top;
top=p;
return * this;
}
template< class T>
LinkedStack<T>& LinkedStack<T>::Delete(T& x)
{
if(IsEmpty())
throw " Out of Bounds() ";
x=top->data;
Node<T> *p;
p=top->link;
delete top;
top=p;
return * this;
}
int main( void)
{
int x;
LinkedStack< int> S;
try {S.Add( 1).Add( 2).Add( 3).Add( 4);}
catch (...) {
cout << " Could not complete additions " << endl;
}
cout << " Stack should be 1234 " << endl;
cout << " Stack top is " << S.Top() << endl;
try {
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
S.Delete(x);
cout << " Deleted " << x << endl;
}
catch (...) {
cout << " Last delete failed " << endl;
}
}
(1)括号匹配
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stack>
#include < string>
using namespace std;
void PrintMatchedPairs( string expr){
stack< int> s;
string::iterator it;
int i= 1;
for(it=expr.begin();it!=expr.end();++it,++i){
if(*it== ' ( ')
s.push(i);
else if(*it== ' ) ')
{
if(s.empty()){
cout<< " No match for left parentthesis at "<<i<<endl;
}
else{
int t=s.top();
cout<<t<< " "<<i<<endl;
s.pop();
}
}
}
while(!s.empty()) {
int t=s.top();
cout<< " No match for left parentthesis at "<<t<<endl;
s.pop();
}
}
int main( void)
{
const int MaxLength= 200;
char expr[MaxLength];
cout << " Type an expression of length at most "
<< MaxLength << endl;
cin.getline(expr, MaxLength);
cout << " The pairs of matching parentheses in "
<< endl;
cout<<expr<<endl;
cout << " are " << endl;
string expr2(expr);
PrintMatchedPairs(expr2);
}
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stack>
using namespace std;
void TowersofHanoi( int n, int x, int y, int z){
if(n> 0){
TowersofHanoi(n- 1,x,z,y);
cout<< " move top disk from tower "<<x<< " to top of tower "<<y<<endl;
TowersofHanoi(n- 1,z,y,x);
}
}
int main(){
cout << " Moves for a three disk problem are " << endl;
TowersofHanoi( 3, 1, 2, 3);
}
网上给出的一个很不错的非递归方式的汉诺塔实现,具体见这,下面是代码:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
// 圆盘的个数最多为64
const int MAX = 64;
// 用来表示每根柱子的信息
struct st{
int s[MAX]; // 柱子上的圆盘存储情况
int top; // 栈顶,用来最上面的圆盘
char name; // 柱子的名字,可以是A,B,C中的一个
int Top() // 取栈顶元素
{
return s[top];
}
int Pop() // 出栈
{
return s[top--];
}
void Push( int x) // 入栈
{
s[++top] = x;
}
} ;
long Pow( int x, int y); // 计算x^y
void Creat(st ta[], int n); // 给结构数组设置初值
void Hannuota(st ta[], long max); // 移动汉诺塔的主要函数
int main( void)
{
int n;
cin >> n; // 输入圆盘的个数
st ta[ 3]; // 三根柱子的信息用结构数组存储
Creat(ta, n); // 给结构数组设置初值
long max = Pow( 2, n) - 1; // 动的次数应等于2^n - 1
Hannuota(ta, max); // 移动汉诺塔的主要函数
return 0;
}
void Creat(st ta[], int n)
{
ta[ 0].name = ' A ';
ta[ 0].top = n- 1;
// 把所有的圆盘按从大到小的顺序放在柱子A上
for ( int i= 0; i<n; i++)
ta[ 0].s[i] = n - i;
// 柱子B,C上开始没有没有圆盘
ta[ 1].top = ta[ 2].top = 0;
for ( int i= 0; i<n; i++)
ta[ 1].s[i] = ta[ 2].s[i] = 0;
// 若n为偶数,按顺时针方向依次摆放 A B C
if (n% 2 == 0)
{
ta[ 1].name = ' B ';
ta[ 2].name = ' C ';
}
else // 若n为奇数,按顺时针方向依次摆放 A C B
{
ta[ 1].name = ' C ';
ta[ 2].name = ' B ';
}
}
long Pow( int x, int y)
{
long sum = 1;
for ( int i= 0; i<y; i++)
sum *= x;
return sum;
}
void Hannuota(st ta[], long max)
{
int k = 0; // 累计移动的次数
int i = 0;
int ch;
while (k < max)
{
// 按顺时针方向把圆盘1从现在的柱子移动到下一根柱子
ch = ta[i% 3].Pop();
ta[(i+ 1)% 3].Push(ch);
cout << ++k << " : " <<
" Move disk " << ch << " from " << ta[i% 3].name <<
" to " << ta[(i+ 1)% 3].name << endl;
i++;
// 把另外两根柱子上可以移动的圆盘移动到新的柱子上
if (k < max)
{
// 把非空柱子上的圆盘移动到空柱子上,当两根柱子都为空时,移动较小的圆盘
if (ta[(i+ 1)% 3].Top() == 0 ||
ta[(i- 1)% 3].Top() > 0 &&
ta[(i+ 1)% 3].Top() > ta[(i- 1)% 3].Top())
{
ch = ta[(i- 1)% 3].Pop();
ta[(i+ 1)% 3].Push(ch);
cout << ++k << " : " << " Move disk "
<< ch << " from " << ta[(i- 1)% 3].name
<< " to " << ta[(i+ 1)% 3].name << endl;
}
else
{
ch = ta[(i+ 1)% 3].Pop();
ta[(i- 1)% 3].Push(ch);
cout << ++k << " : " << " Move disk "
<< ch << " from " << ta[(i+ 1)% 3].name
<< " to " << ta[(i- 1)% 3].name << endl;
}
}
}
}
本人使用STL中的stack对上面的代码进行了一下修改:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
public:
stack< int> st;
char name;
};
int Pow( int x, int y){
int sum= 1;
for( int i= 0;i<y;i++)
sum*=x;
return sum;
}
void Hanoi( int N){
Tower ta[ 3];
ta[ 0].name= ' A ';
for( int i= 0;i<N;i++)
ta[ 0].st.push(N-i);
if(N% 2== 0){
ta[ 1].name= ' B ';
ta[ 2].name= ' C ';
}
else{
ta[ 1].name= ' C ';
ta[ 2].name= ' B ';
}
int k= 0;
int i= 0;
int ch;
int max=Pow( 2,N)- 1;
while(k<max){
ch=ta[i% 3].st.top();
ta[i% 3].st.pop();
ta[(i+ 1)% 3].st.push(ch);
cout<<++k<< " : Move disk "<<ch<< " from "<<ta[i% 3].name<< " to "<<ta[(i+ 1)% 3].name<<endl;
i++;
if(k<max){
if(ta[(i+ 1)% 3].st.empty()||!ta[(i- 1)% 3].st.empty()&&ta[(i+ 1)% 3].st.top()>ta[(i- 1)% 3].st.top()){
ch=ta[(i- 1)% 3].st.top();
ta[(i- 1)% 3].st.pop();
ta[(i+ 1)% 3].st.push(ch);
cout<<++k<< " : Move disk "<<ch<< " from "<<ta[(i- 1)% 3].name<< " to "<<ta[(i+ 1)% 3].name<<endl;
}
else{
ch=ta[(i+ 1)% 3].st.top();
ta[(i+ 1)% 3].st.pop();
ta[(i- 1)% 3].st.push(ch);
cout<<++k<< " : Move disk "<<ch<< " from "<<ta[(i+ 1)% 3].name<< " to "<<ta[(i- 1)% 3].name<<endl;
}
}
}
}
下图是对两种方法(递归和迭代)的比较:
(3)火车车厢重排
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
bool Hold( int c, int &minH, int& minS,vector<stack< int> >& H, int k, int n){
int BestTrack= 0,BestTop=n+ 1,x;
for( int i= 1;i<=k;i++){
if(!H[i].empty()){
x=H[i].top();
if(c<x&&x<BestTop){
BestTop=x;
BestTrack=i;
}
}
else{
if(!BestTrack)
BestTrack=i;
}
}
if(!BestTrack)
return false;
H[BestTrack].push(c);
cout<< " Move car "<<c<< " from input to holding track "<<BestTrack<<endl;
if(c<minH) {
minH=c;
minS=BestTrack;
}
return true;
}
void Output( int& minH, int& minS,vector<stack< int> >& H, int k, int n){
int c;
c=H[minS].top();
H[minS].pop();
cout<< " Move car "<<minH<< " from holding track "<<minS<< " to output "<<endl;
minH=n+ 2;
for( int i= 1;i<=k;i++)
{
if(!H[i].empty()&&(c=H[i].top())<minH){
minH=c;
minS=i;
}
}
}
bool Railroad( int p[], int n, int k){
vector<stack< int> > H(k+ 1);
int NowOut= 1;
int minH=n+ 1;
int minS;
for( int i= 1;i<=n;i++){
if(p[i]==NowOut){
cout<< " Move car "<<p[i]<< " from input to output "<<endl;
NowOut++;
while(minH==NowOut){
Output(minH,minS,H,k,n);
NowOut++;
}
}
else{
if(!Hold(p[i],minH,minS,H,k,n))
return false;
}
}
return true;
}
int main(){
int p[ 10] = { 0, 3, 6, 9, 2, 4, 7, 1, 8, 5};
cout << " Input permutation is 0369247185 " << endl;
Railroad(p, 9, 3);
}
(4)开关盒布线
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <stack>
using namespace std;
bool CheckBox( int net[], int n){
stack< int> s;
for( int i= 0;i<n;i++){
if(s.empty()){
s.push(i);
}
else{
if(net[i]==net[s.top()]){
cout<< " Wiring from "<<(i+ 1)<< " to "<<(s.top()+ 1)<<endl;
s.pop();
}
else
s.push(i);
}
}
if(s.empty()) {
cout<< " Switch box is routbale "<<endl;
return true;
}
else {
cout<< " Switch box is not routbale ";
return false;
}
}
int main(){
int net[]={ 1, 2, 2, 1, 3, 3, 4, 4};
int n= sizeof(net)/ sizeof(net[ 0]);
CheckBox(net,n);
}
(5)离线等价类
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <list>
#include <stack>
#include <vector>
using namespace std;
int main(){
int n,r;
cout<< " Enter number of elements "<<endl;
cin>>n;
if(n< 2){
cerr<< " Too few elements "<<endl;
return 1;
}
cout<< " Enter number of relations "<<endl;
cin>>r;
if(r< 1){
cerr<< " Too few relations "<<endl;
return 1;
}
vector<list< int> > chain(n+ 1);
for( int i= 1;i<=r;i++)
{
cout<< " Enter next relation/pair "<<endl;
int a,b;
cin>>a>>b;
chain[a].push_front(b);
chain[b].push_front(a);
}
stack< int> s;
vector< bool> out(n+ 1);
for( int i= 1;i<=n;i++)
out[i]= false;
for( int i= 1;i<=n;i++){
if(! out[i]){
cout<< " Next class is: "<<i<< ' ';
out[i]= true;
s.push(i);
list< int>::const_iterator it;
while(!s.empty()){
int j=s.top();
s.pop();
for(it=chain[j].begin();it!=chain[j].end();++it)
if(! out[*it]){
cout<<*it<< ' ';
out[*it]= true;
s.push(*it);
}
}
cout<<endl;
}
}
}
(6)迷宫老鼠
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <fstream>
#include <stack>
#include <cstdio>
using namespace std;
struct Position{
int x;
int y;
};
Position operator+(Position& a,Position& b){
Position p;
p.x=a.x+b.x;
p.y=a.y+b.y;
return p;
}
int **maze,m;
bool **flag;
stack<Position> path;
const char * const red = " \033[0;40;31m ";
const char * const normal = " \033[0m ";
template < class T>
void make2darray(T ** &maze, int w, int h){
maze= new T*[w];
T *mem= new T[w*h];
for( int i= 0;i<w;i++)
maze[i]=mem+i*h;
}
template < class T>
void free2darray(T** maze){
if(maze){
if(*maze)
delete[] *maze;
delete[] maze;
}
}
bool InputMaze( const char *file)
{ // Input the maze.
ifstream inf(file);
inf >> m;
cout << " maze size: "<<m<< endl;
make2darray(maze, m, m);
for ( int i= 0; i<m; i++)
for ( int j= 0; j<m; j++)
inf >> maze[i][j];
cout << " the maze: " << endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
cout<< maze[i][j]<< " ";
cout<<endl;
}
cout<<endl;
make2darray(flag, m, m);
for ( int i= 0; i<m; i++)
for ( int j= 0; j<m; j++)
flag[i][j]= false;
return true;
}
void OutputPath()
{ // Output path to exit.
cout << " The path is " << endl;
Position here;
while (!path.empty()) {
here=path.top();
path.pop();
cout << here.x << ' ' << here.y << endl;
flag[here.x][here.y]= true;
}
cout<< " Another: "<<endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
{
if(flag[i][j])
printf( " %s%d%s ",red,maze[i][j],normal);
else
printf( " %d ",maze[i][j]);
}
printf( " \n ");
}
printf( " \n ");
}
bool FindPath(){
Position here={ 0, 0};
Position offset[ 4]={{ 0, 1},{ 1, 0},{ 0,- 1},{- 1, 0}};
maze[ 0][ 0]= 1;
int i= 0;
while(here.x!=m- 1||here.y!=m- 1){
Position location;
int lx,ly;
while(i< 4){
location=here+offset[i];
lx=location.x;
ly=location.y;
if(!(lx< 0||ly< 0||lx>m- 1||ly>m- 1)){
if(maze[lx][ly]== 0)
break;
}
i++;
}
if(i< 4){
path.push(here);
here=location;
maze[lx][ly]= 1;
i= 0;
}
else{
if(path.empty())
return false;
Position next;
next=path.top();
path.pop();
if(next.x==here.x)
i= 2+next.y-here.y;
else
i= 3+next.x-here.x;
here=next;
}
}
path.push(here);
return true;
}
int main(){
InputMaze( " maze.dat ");
if (FindPath()) OutputPath();
else cout << " No path " << endl;
free2darray(maze);
free2darray(flag);
}
迷宫数据:
10
0 1 1 1 1 1 0 0 0 0
0 0 0 0 0 1 0 1 0 0
0 0 0 1 0 1 0 0 0 0
0 1 0 1 0 1 0 1 1 0
0 1 0 1 0 1 0 1 0 0
0 1 1 1 0 1 0 1 0 1
0 1 0 0 0 1 0 1 0 1
0 1 0 1 1 1 0 1 0 0
1 0 0 0 0 0 0 1 0 0
0 0 0 0 1 1 1 1 0 0
程序输出如下:
第6章 队列
队列是一个先进先出( first-in-first-out, FIFO)的线性表
1. 公式化实现队列
实现代码:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template < class T>
class Queue{
public:
Queue( int Size= 10);
~Queue(){
delete [] queue;
}
bool IsEmpty() const{
return front==rear;
}
bool IsFull() const{
return ((rear+ 1)%MaxSize==front)? true: false;
}
T First() const;
T Last() const;
Queue<T>& Add( const T& x);
Queue<T>& Delete(T& x);
private:
int front;
int rear;
int MaxSize;
T *queue;
};
template < class T>
Queue<T>::Queue( int size)
{
MaxSize=size;
queue= new T[size];
front=rear= 0;
}
template < class T>
T Queue<T>::First() const
{
if(IsEmpty())
throw " Out of Bounds ";
return queue[(front+ 1)%MaxSize];
}
template < class T>
T Queue<T>::Last() const
{
if(IsEmpty())
throw " Out of Bounds ";
return queue[rear];
}
template < class T>
Queue<T>& Queue<T>::Add( const T& x)
{
if(IsFull())
throw " No memorry ";
rear=(rear+ 1)%MaxSize;
queue[rear]=x;
return * this;
}
template < class T>
Queue<T>& Queue<T>::Delete(T& x)
{
if(IsEmpty())
throw " Out of Bounds ";
front=(front+ 1)%MaxSize;
x=queue[front];
return * this;
}
int main( void)
{
Queue< int> Q( 3);
int x;
try {Q.Add( 1).Add( 2).Add( 3).Add( 4);
cout << " No queue add failed " << endl;}
catch (...)
{cout << " A queue add failed " << endl;}
cout << " Queue is now 123 " << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
cout << Q.First() << " is at front " << endl;
cout << Q.Last() << " is at end " << endl;
try {
Q.Delete(x);
cout << " Deleted " << x << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
cout << " No queue delete failed " << endl;
}
catch (...)
{cout << " A delete has failed " << endl;}
}
2. 链表描述
实现代码:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template < class T>
class LinkedQueue;
template < class T>
class Node{
friend class LinkedQueue<T>;
private:
T data;
Node<T> *link;
};
template < class T>
class LinkedQueue{
public:
LinkedQueue(){
front=rear= 0;
}
~LinkedQueue();
bool IsEmpty() const{
return (front)? false: true;
}
bool IsFull() const;
T First() const;
T Last() const;
LinkedQueue<T>& Add( const T& x);
LinkedQueue<T>& Delete(T& x);
private:
Node<T>*front;
Node<T>*rear;
};
template < class T>
LinkedQueue<T>::~LinkedQueue()
{
Node<T>*next;
while(front){
next=front->link;
delete front;
front=next;
}
}
template < class T>
bool LinkedQueue<T>::IsFull() const
{
Node<T>*p;
try{
p= new Node<T>;
delete p;
return false;
}
catch(...){
return true;
}
}
template < class T>
T LinkedQueue<T>::First() const
{
if(IsEmpty())
throw " Out of Bounds ";
return front->data;
}
template < class T>
T LinkedQueue<T>::Last() const
{
if(IsEmpty())
throw " Out of Bounds ";
return rear->data;
}
template < class T>
LinkedQueue<T>& LinkedQueue<T>::Add( const T& x)
{
Node<T>*p= new Node<T>;
p->data=x;
p->link= 0;
if(front) rear->link=p;
else
front=p;
rear=p;
return * this;
}
template < class T>
LinkedQueue<T>& LinkedQueue<T>::Delete(T& x)
{
if(IsEmpty())
throw " Out of Bounds ";
x=front->data;
Node<T>*p;
p=front->link;
delete front;
front=p;
return * this;
}
int main( void)
{
LinkedQueue< int> Q;
int x;
try {Q.Add( 1).Add( 2).Add( 3).Add( 4);
cout << " No queue add failed " << endl;}
catch (...)
{cout << " A queue add failed " << endl;}
cout << " Queue is now 1234 " << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
cout << Q.First() << " is at front " << endl;
cout << Q.Last() << " is at end " << endl;
try {
Q.Delete(x);
cout << " Deleted " << x << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
Q.Delete(x);
cout << " Deleted " << x << endl;
cout << " No queue delete failed " << endl;
}
catch (...)
{cout << " A delete has failed " << endl;}
}
3. 队列的应用
(1)火车重排
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
bool Hold( int c, int &minH, int& minQ,vector<queue< int> >& H, int k){
int BestTrack= 0,BestLast= 0,x;
for( int i= 1;i<=k;i++){
if(!H[i].empty()){
x=H[i].back();
if(c>x&&x>BestLast){
BestLast=x;
BestTrack=i;
}
}
else{
if(!BestTrack)
BestTrack=i;
}
}
if(!BestTrack)
return false;
H[BestTrack].push(c);
cout<< " Move car "<<c<< " from input to holding track "<<BestTrack<<endl;
if(c<minH) {
minH=c;
minQ=BestTrack;
}
return true;
}
void Output( int& minH, int& minQ,vector<queue< int> >& H, int k, int n){
int c;
c=H[minQ].front();
H[minQ].pop();
cout<< " Move car "<<minH<< " from holding track "<<minQ<< " to output "<<endl;
minH=n+ 2;
for( int i= 1;i<=k;i++)
{
if(!H[i].empty()&&(c=H[i].front())<minH){
minH=c;
minQ=i;
}
}
}
bool Railroad( int p[], int n, int k){
vector<queue< int> > H(k);
k--;
int NowOut= 1;
int minH=n+ 1;
int minQ;
for( int i= 1;i<=n;i++){
if(p[i]==NowOut){
cout<< " Move car "<<p[i]<< " from input to output "<<endl;
NowOut++;
while(minH==NowOut){
Output(minH,minQ,H,k,n);
NowOut++;
}
}
else{
if(!Hold(p[i],minH,minQ,H,k))
return false;
}
}
return true;
}
int main(){
int p[ 10] = { 0, 3, 6, 9, 2, 4, 7, 1, 8, 5};
cout << " Input permutation is 0369247185 " << endl;
Railroad(p, 9, 3);
}
不使用队列的实现:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
// no explicted queue used
#include <iostream>
#include <vector>
using namespace std;
bool Hold( int c,vector< int>& last,vector< int>& track, int k){
int BestTrack= 0,BestLast= 0;
for( int i= 1;i<=k;i++){
if(last[i]){
if(c>last[i]&&last[i]>BestLast){
BestLast=last[i];
BestTrack=i;
}
}
else{
if(!BestTrack)
BestTrack=i;
}
}
if(!BestTrack)
return false;
track[c]=BestTrack;
last[BestTrack]=c;
cout<< " Move car "<<c<< " from input to holding track "<<BestTrack<<endl;
return true;
}
void Output( int NowOut, int Track, int& Last){
cout<< " Move car "<<NowOut<< " from holding track "<<Track<< " to output "<<endl;
if(NowOut==Last)
Last= 0;
}
bool Railroad( int p[], int n, int k){
vector< int> last(k+ 1);
vector< int> track(n+ 1);
for( int i= 1;i<=k;i++)
last[i]= 0;
for( int i= 1;i<=n;i++)
track[i]= 0;
k--;
int NowOut= 1;
for( int i= 1;i<=n;i++){
if(p[i]==NowOut){
cout<< " Move car "<<p[i]<< " from input to output "<<endl;
NowOut++;
while(NowOut<=n&&track[NowOut]){
Output(NowOut,track[NowOut],last[NowOut]);
NowOut++;
}
}
else{
if(!Hold(p[i],last,track,k))
return false;
}
}
return true;
}
int main(){
int p[ 10] = { 0, 3, 6, 9, 2, 4, 7, 1, 8, 5};
cout << " Input permutation is 0369247185 " << endl;
Railroad(p, 9, 3);
}
(2)电路布线
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <fstream>
#include <queue>
#include <cstdio>
using namespace std;
struct Position{
int x;
int y;
};
Position operator+( const Position& a, const Position& b){
Position p;
p.x=a.x+b.x;
p.y=a.y+b.y;
return p;
}
bool operator==( const Position& a, const Position& b){
return (a.x==b.x&&a.y==b.y);
}
Position operator-( const Position& a, int t){
Position temp;
temp.x=a.x-t;
temp.y=a.y-t;
return temp;
}
Position operator+( const Position& a, int t){
Position temp;
temp.x=a.x+t;
temp.y=a.y+t;
return temp;
}
istream& operator>>(istream& is,Position& ps){
is>>ps.x>>ps.y;
return is;
}
ostream& operator<<(ostream& os, const Position& ps){
os<< " ( "<<ps.x<< " , "<<ps.y<< " ) ";
return os;
}
int **grid,m;
bool **flag;
const char * const red = " \033[0;40;31m ";
const char * const normal = " \033[0m ";
template < class T>
void make2darray(T ** &grid, int w, int h){
grid= new T*[w];
T *mem= new T[w*h];
for( int i= 0;i<w;i++)
grid[i]=mem+i*h;
}
template < class T>
void free2darray(T** maze){
if(maze){
if(*maze)
delete[] *maze;
delete[] maze;
}
}
bool Inputgrid( const char *file,Position& start,Position& finish)
{ // Input the grid.
ifstream inf(file);
inf >> m;
cout << " grid size: "<<m<< endl;
make2darray(grid, m, m);
inf>>start;
inf>>finish;
start=start- 1;
finish=finish- 1;
cout<< " start: "<<start<<endl;
cout<< " finish: "<<finish<<endl;
for ( int i= 0; i<m; i++)
for ( int j= 0; j<m; j++)
inf >> grid[i][j];
cout << " the grid: " << endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
cout<< grid[i][j]<< " ";
cout<<endl;
}
cout<<endl;
make2darray(flag, m, m);
for ( int i= 0; i<m; i++)
for ( int j= 0; j<m; j++)
flag[i][j]= false;
return true;
}
void OutputPath(vector<Position>& path)
{ // Output path to exit.
cout << " The path is " << endl;
vector<Position>::const_iterator it;
for(it=path.begin();it!=path.end();++it){
cout<<*it<<endl;
flag[it->x][it->y]= true;
}
cout<< " Another: "<<endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
{
if(flag[i][j])
printf( " %s%d%s ",red,grid[i][j],normal);
else
printf( " %d ",grid[i][j]);
}
printf( " \n ");
}
printf( " \n ");
}
bool FindPath( const Position& start, const Position& finish,vector<Position>& path){
// if((start.x==finish.x)&&(start.y==finish.y)){
if((start==finish)){
return true;
}
Position here=start;
Position nbr;
const int NumOfNbrs= 4;
Position offset[]={{ 0, 1},{ 1, 0},{ 0,- 1},{- 1, 0}};
grid[start.x][start.y]= 2;
queue<Position> Q;
int lx,ly;
do{
for( int i= 0;i<NumOfNbrs;i++){
nbr=here+offset[i];
lx=nbr.x;
ly=nbr.y;
if(!(lx< 0||ly< 0||lx>m- 1||ly>m- 1)){
if(grid[nbr.x][nbr.y]== 0){
grid[nbr.x][nbr.y]=grid[here.x][here.y]+ 1;
if(nbr==finish)
break;
Q.push(nbr);
}
}
}
if(nbr==finish)
break;
if(Q.empty())
return false;
here=Q.front();
Q.pop();
} while( 1);
int PathLen=grid[finish.x][finish.y]- 2;
path.resize(PathLen);
here=finish;
for( int j=PathLen- 1;j>= 0;j--){
path[j]=here;
for( int i= 0;i<NumOfNbrs;i++){
nbr=here+offset[i];
lx=nbr.x;
ly=nbr.y;
if(!(lx< 0||ly< 0||lx>m- 1||ly>m- 1)){
if(grid[nbr.x][nbr.y]==j+ 2)
break;
}
}
here=nbr;
}
return true;
}
int main(){
Position start,finish;
Inputgrid( " wire.dat ",start,finish);
vector<Position> path;
if (FindPath(start,finish,path))
OutputPath(path);
else
cout << " No path " << endl;
free2darray(grid);
free2darray(flag);
}
布线路图:
7
3 2
4 6
0 0 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 0 0
1 0 0 0 1 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
程序输出如下:
(3)识别图元
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <fstream>
#include <queue>
#include <cstdio>
using namespace std;
struct Position{
int x;
int y;
};
Position operator+( const Position& a, const Position& b){
Position p;
p.x=a.x+b.x;
p.y=a.y+b.y;
return p;
}
int **pixel,m;
const char *color[]={ " \033[0;40;31m ", " \033[0;40;32m ", " \033[0;40;33m ", " \033[0;40;34m ", " \033[0;40;35m ", " \033[0;40;36m "};
const char * const normal = " \033[0m ";
template < class T>
void make2darray(T ** &pixel, int w, int h){
pixel= new T*[w];
T *mem= new T[w*h];
for( int i= 0;i<w;i++)
pixel[i]=mem+i*h;
}
template < class T>
void free2darray(T** maze){
if(maze){
if(*maze)
delete[] *maze;
delete[] maze;
}
}
void InputImage( const char*file)
{ // Input the pixel.
ifstream inf(file);
inf >> m;
cout << " pixel size: "<<m<< endl;
make2darray(pixel, m, m);
for ( int i= 0; i<m; i++)
for ( int j= 0; j<m; j++)
inf >> pixel[i][j];
cout << " the pixel: " << endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
cout<< pixel[i][j];
cout<<endl;
}
cout<<endl;
}
void OutputImage()
{ // Output path to exit.
cout<< " Another: "<<endl;
for ( int i= 0; i<m; i++) {
for ( int j= 0; j<m; j++)
{
if(pixel[i][j]> 1)
printf( " %s%d%s ",color[pixel[i][j]- 2],pixel[i][j],normal);
else
printf( " %d ",pixel[i][j]);
}
printf( " \n ");
}
printf( " \n ");
}
void Label(){
const int NumOfNbrs= 4;
Position offset[]={{ 0, 1},{ 1, 0},{ 0,- 1},{- 1, 0}};
Position here,nbr;
queue<Position> Q;
int id= 1;
for( int r= 0;r<m;r++){
for( int c= 0;c<m;c++){
if(pixel[r][c]== 1){
pixel[r][c]=++id;
here.x=r;
here.y=c;
int lx,ly;
do{
for( int i= 0;i<NumOfNbrs;i++){
nbr=here+offset[i];
lx=nbr.x;
ly=nbr.y;
if(!(lx< 0||ly< 0||lx>m- 1||ly>m- 1)){
if(pixel[lx][ly]== 1){
pixel[lx][ly]=id;
Q.push(nbr);
}
}
}
if(Q.empty())
break;
here=Q.front();
Q.pop();
} while( 1);
}
}
}
}
int main(){
const char*file= " image.dat ";
InputImage(file);
cout << " The input image is " << endl;
OutputImage();
Label();
cout << " The labeled image is " << endl;
OutputImage();
}
图元数据:
0 0 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 0 1 0 0
0 0 0 1 1 0 0
1 0 0 0 1 0 0
1 1 1 0 0 0 0
1 1 1 0 0 0 0
程序输出:
1. 线性表来实现字典,该线性表按关键字从左到右依次增大。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template < class E, class K> class SortedChain;
template < class E, class K>
class SortedChainNode {
friend class SortedChain<E,K>;
private:
E data;
K key;
SortedChainNode<E,K> *link;
};
template< class E, class K>
class SortedChain{
public:
SortedChain(){
first= 0;
}
~SortedChain();
bool IsEmpty() const{
return first== 0;
}
int Length() const;
bool Search( const K& k,E& e) const;
SortedChain<E,K>& Delete( const K& k,E& e);
SortedChain<E,K>& Insert( const K& k, const E& e);
SortedChain<E,K>& DistinctInsert( const K&k, const E& e);
void Output(ostream& out) const;
private:
SortedChainNode<E,K> *first;
};
template< class E, class K>
SortedChain<E,K>::~SortedChain()
{
SortedChainNode<E,K>* next;
while(first){
next=first->link;
delete first;
first=next;
}
}
template< class E, class K>
int SortedChain<E,K>::Length() const
{
SortedChainNode<E,K>* p=first;
int len= 0;
while(p){
p=p->link;
len++;
}
return len;
}
template< class E, class K>
bool SortedChain<E,K>::Search( const K& k,E& e) const
{
SortedChainNode<E,K> *p=first;
while(p&&p->key<k)
p=p->link;
if(p&&p->key==k) {
e=p->data;
return true;
}
return false;
}
template< class E, class K>
SortedChain<E,K>& SortedChain<E,K>::Delete( const K& k,E& e)
{
SortedChainNode<E,K>*p=first,*tp= 0;
while(p&&p->key<k){
tp=p;
p=p->link;
}
if(p&&p->key==k){
e=p->data;
if(tp)
tp->link=p->link;
else
first=p->link;
delete p;
return * this;
}
throw " Bad Input ";
return * this;
}
template< class E, class K>
SortedChain<E,K>& SortedChain<E,K>::Insert( const K& k, const E& e)
{
SortedChainNode<E,K>*p=first,*tp= 0;
while(p&&p->key<k){
tp=p;
p=p->link;
}
SortedChainNode<E,K> *q= new SortedChainNode<E,K>;
q->key=k;
q->data=e;
q->link=p;
if(tp)
tp->link=q;
else
first=q;
return * this;
}
template< class E, class K>
SortedChain<E,K>& SortedChain<E,K>::DistinctInsert( const K& k, const E& e)
{
SortedChainNode<E,K>*p=first,*tp= 0;
while(p&&p->key<k){
tp=p;
p=p->link;
}
if(p&&p->data==e)
throw " Bad Input ";
SortedChainNode<E,K> *q= new SortedChainNode<E,K>;
q->key=k;
q->data=e;
q->link=p;
if(tp)
tp->link=q;
else
first=q;
return * this;
}
template< class E, class K>
void SortedChain<E,K>::Output(ostream& out) const
{
SortedChainNode<E,K>*p;
p=first;
while(p){
out<< " ( "<<p->key<< " , "<<p->data<< " ) ";
p=p->link;
}
}
template< class E, class K>
ostream& operator<<(ostream& out, const SortedChain<E,K>& x){
x.Output( out);
return out;
}
int main( void)
{
SortedChain< int, int> Z;
int x;
Z.Insert( 2, 2).Insert( 6, 6).Insert( 4, 4);
cout << " The chain is " << Z << endl;
cout << " Its length is " << Z.Length() << endl;
Z.Delete( 2,x);
cout << " Deleted " << x << endl;
cout << Z << endl;
Z.Insert( 1, 1).Delete( 6,x);
cout << Z << endl;
Z.Insert( 8, 8).Insert( 9, 9).Search( 8,x);
cout << " Found " << x << endl;
Z.Insert( 7, 7).Delete( 9,x);
cout << Z << endl;
try {Z.DistinctInsert( 7, 7);}
catch (...)
{cout << " Attempt to insert duplicate element " << endl;}
cout << Z << endl;
Z.DistinctInsert( 10, 10);
cout << Z << endl;
}
(1)理想情况
跳表的实现代码:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <iostream>
#include <cmath>
#include <cstdlib>
using namespace std;
template < class E, class K>
class SkipList;
template < class E, class K>
class SkipNode{
friend class SkipList<E,K>;
SkipNode( int size){
link= new SkipNode<E,K>*[size];
}
~SkipNode(){
delete[] link;
}
private:
E data;
K key;
SkipNode<E,K>**link;
};
template< class E, class K>
class SkipList{
public:
SkipList(K large, int MaxE= 10000, float p= 0.5);
~SkipList();
bool Search( const K& k,E& e) const;
SkipList<E,K>& Insert( const K& k, const E& e);
SkipList<E,K>& Delete( const K& k,E& e);
void Output();
private:
int Level();
SkipNode<E,K>* SaveSearch( const K& k);
int MaxLevel;
int Levels;
int CutOff;
K TailKey;
SkipNode<E,K>* head;
SkipNode<E,K>* tail;
SkipNode<E,K>* *last;
};
template< class E, class K>
SkipList<E,K>::SkipList(K large, int MaxE, float p)
{
CutOff=p*RAND_MAX;
MaxLevel=ceil(log(MaxE* 1.0)/log( 1/p))- 1;
TailKey=large;
Levels= 0;
head= new SkipNode<E,K>(MaxLevel+ 1);
tail= new SkipNode<E,K>( 0);
last= new SkipNode<E,K>* [MaxLevel+ 1];
tail->key=large;
for( int i= 0;i<=MaxLevel;i++)
head->link[i]=tail;
}
template< class E, class K>
SkipList<E,K>::~SkipList()
{
SkipNode<E,K> *next;
while(head!=tail){
next=head->link[ 0];
delete head;
head=next;
}
delete tail;
delete [] last;
}
template< class E, class K>
bool SkipList<E,K>::Search( const K& k,E& e) const
{
if(k>=TailKey)
return false;
SkipNode<E,K> *p=head;
for( int i=Levels;i>= 0;i--)
while(p->link[i]->key<k)
p=p->link[i];
e=p->link[ 0]->data;
K tmp=p->link[ 0]->key;
return e==tmp;
}
template< class E, class K>
SkipList<E,K>& SkipList<E,K>::Insert( const K& k, const E& e)
{
if(k>=TailKey)
throw " Bad Input ";
SkipNode<E,K> *p=SaveSearch(k);
if(p->data==e)
throw " Bad Input ";
int lev=Level();
if(lev>Levels){
lev=++Levels;
last[lev]=head;
}
SkipNode<E,K> *y= new SkipNode<E,K>(lev+ 1);
y->data=e;
y->key=k;
for( int i= 0;i<=lev;i++){
y->link[i]=last[i]->link[i];
last[i]->link[i]=y;
}
return * this;
}
template< class E, class K>
SkipList<E,K>& SkipList<E,K>::Delete( const K& k,E& e)
{
if(k>=TailKey)
throw " Bad Input ";
SkipNode<E,K> *p=SaveSearch(k);
if(p->data==e)
throw " Bad Input ";
for( int i= 0;i<=Levels&&last[i]->link[i]==p;i++)
last[i]->link[i]=p->link[i];
while(Levels> 0&&head->link[Levels]==tail)
Levels--;
e=p->data;
delete p;
return * this;
}
template< class E, class K>
int SkipList<E,K>::Level()
{
int lev= 0;
while(rand()<=CutOff)
lev++;
return lev<=MaxLevel?lev:MaxLevel;
}
template< class E, class K>
SkipNode<E,K>* SkipList<E,K>::SaveSearch( const K& k)
{
SkipNode<E,K> *p=head;
for( int i=Levels;i>= 0;i--){
while(p->link[i]->key<k)
p=p->link[i];
last[i]=p;
}
return p->link[ 0];
}
template< class E, class K>
void SkipList<E,K>::Output()
{
SkipNode<E,K> *y = head->link[ 0];
for (; y != tail; y = y->link[ 0])
cout << " ( "<<y->key<< " , "<< y->data << " ) ";
cout << endl;
}
int main( void)
{
SkipList< int, long> S( 10001, 100, 0.5);
int i, n = 20;
int data;
long key;
for (i = 1; i <= n; i++) {
data = i;
key = 2*i;
S.Insert(key,data);
}
S.Output();
for (i= 1; i <= n+ 1; i++) {
data = n+i;
key = 2*i- 1;
try {S.Insert(key,data);}
catch (...)
{cout << " Unable to insert duplicate ( " <<key<< " , "<<data<< " ) "<< endl;}
}
S.Output();
for (i = 1; i <= n+ 1; i++) {
key = 2*i- 1;
try {S.Delete(key,data);
cout << " Deleted ( " << key << " , " << data << " ) "<< endl;}
catch (...)
{cout << " Delete of " << ( 2*i- 1) << " failed " << endl;}
}
S.Output();
}
#endif
(1)线性开型寻址
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
using namespace std;
template< class E, class K>
class HashTable{
public:
HashTable( int divisior= 11);
~HashTable(){
delete[] ht;
delete[] empty;
}
bool Search( const K& k,E& e) const;
HashTable<E,K>& Insert( const E& e);
void Output();
private:
int hSearch( const K& k) const;
int D;
E *ht;
bool *empty;
};
template< class E, class K>
HashTable<E,K>::HashTable( int divisior)
{
D=divisior;
ht= new E[D];
empty= new bool[D];
for( int i= 0;i<D;i++)
empty[i]= true;
}
template< class E, class K>
bool HashTable<E,K>::Search( const K& k,E& e) const
{
int b=hSearch(k);
if(empty[b]||ht[b]!=k)
return false;
e=ht[b];
return true;
}
template< class E, class K>
HashTable<E,K>& HashTable<E,K>::Insert( const E& e)
{
K k=e;
int b=hSearch(k);
if(empty[b]){
empty[b]= false;
ht[b]=e;
return * this;
}
if(ht[b]==k)
throw " Bad Input ";
throw " No mem ";
return * this;
}
template< class E, class K>
void HashTable<E,K>::Output()
{
for( int i= 0;i<D;i++){
if(empty[i])
cout<< " empty "<<endl;
else
cout<<ht[i]<<endl;
}
}
template< class E, class K>
int HashTable<E,K>::hSearch( const K& k) const
{
int i=k%D;
int j=i;
do{
if(empty[j]||ht[j]==k)
return j;
j=(j+ 1)%D;
}
while(j!=i);
return j;
}
int main( void)
{
int data;
long key;
HashTable< int, long> h( 11);
data= 80;
h.Insert(data);
data= 40;
h.Insert(data);
data= 65;
h.Insert(data);
h.Output();
data= 58;
h.Insert(data);
data= 24;
h.Insert(data);
cout << ' ' << endl;
h.Output();
data= 2;
h.Insert(data);
data= 13;
h.Insert(data);
data= 46;
h.Insert(data);
data= 16;
h.Insert(data);
data= 7;
h.Insert(data);
data= 21;
h.Insert(data);
cout << ' ' << endl;
h.Output();
data= 99;
try {h.Insert(data);}
catch (...)
{cout << " No memory for 99 " << endl;}
}
(2)链表散列
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <map>
#include <vector>
#include < string>
#include <cstdlib>
using namespace std;
template < class K, class E>
class ChainHashTable{
public:
ChainHashTable( int div= 11):D(div){
tab.resize(div);
}
bool Search( const K& k,E& e) const{
typename map<K,E>::iterator ite;
ite=tab[k%D].find(k);
if(ite==tab[k%D].end())
return false;
e=ite->second;
return true;
}
ChainHashTable& Insert( const K& k, const E& e){
tab[k%D].insert(pair<K,E>(k,e));
return * this;
}
ChainHashTable& Delete( const K& k){
tab[k%D].erase(k);
return * this;
}
void Output(ostream& os) const{
typename map<K,E>::const_iterator ite;
for( int i= 0;i<D;i++){
os<< " tab[ "<<i<< " ]: ";
for(ite=tab[i].begin();ite!=tab[i].end();++ite){
os<< " < "<<ite->first<< " , "<<ite->second<< " > ";
}
os<<endl;
}
}
private:
int D;
vector<map<K,E> > tab;
};
template < class E, class K>
ostream& operator<<(ostream& os, const ChainHashTable<E,K>& cht){
cht.Output(os);
return os;
}
const string letters( " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ ");
string rand_str( int n){
string s(n, ' ');
for( int i= 0;i<n;i++){
int pos=rand()% 52;
s[i]=letters[pos];
}
return s;
}
int main(){
ChainHashTable< int, string> ht( 11);
int N= 20;
for( int i= 0;i<N;i++){
int val=rand()% 100;
string str=rand_str( 10);
ht.Insert(val,str);
}
cout<< " ok "<<endl;
cout<<ht<<endl;
}
实现代码采用了STL中的map:
4. 散列与跳表的比较:
5.应用
LzW压缩
压缩代码的实现如下:下面的代码没有采用上面的等长位编码,而是采用的最显而易见的方式:
map< string,unsigned> mp;
int N=Alpha;
int used=N;
for( int i= 0;i<N;i++){
string key( 1, ' a '+i);
unsigned code=i;
mp.insert(pair< string,unsigned>(key,code));
}
typename map< string,unsigned>::iterator ite;
ostringstream oss;
size_t len=in_str.length();
if(len< 2){
ite=mp.find(in_str.substr( 0, 1));
oss<<ite->second;
}
else{
string pcode;
pcode+=in_str[ 0];
for( int i= 1;i<len;i++){
char c=in_str[i];
string key=pcode+c;
ite=mp.find(key);
if(ite!=mp.end()){
pcode=key;
}
else{
oss<<mp[pcode];
mp.insert(pair< string,unsigned>(key,used++));
pcode=c;
}
}
oss<<mp[pcode];
}
str_code=oss.str();
return mp;
}
LZW解压缩
解压缩代码:与压缩代码是对应的:
map<unsigned, string> mp;
int N=Alpha;
unsigned used=N;
for( int i= 0;i<N;i++){
unsigned key=i;
string code( 1, ' a '+i);
mp.insert(make_pair(key,code));
}
typename map<unsigned, string>::iterator ite;
ostringstream oss;
size_t len=str_code.length();
if(len< 2){
oss<<mp[(unsigned)(str_code[ 0]- ' 0 ')];
}
else{
unsigned pcode=(unsigned)(str_code[ 0]- ' 0 ');
oss<<mp[pcode];
for( int i= 1;i<len;i++){
string prefix=mp[pcode];
char surfix;
string code;
unsigned key=used++;
unsigned ccode=(unsigned)(str_code[i]- ' 0 ');
ite=mp.find(ccode);
if(ite!=mp.end()){
oss<<ite->second;
surfix=(ite->second).at( 0);
code=prefix+surfix;
// unsigned key=used++;
// mp.insert(make_pair(key,code));
}
else{
// string prefix=mp[pcode];
surfix=prefix[ 0];
code=prefix+surfix;
// unsigned key=used++;
oss<<code;
}
mp.insert(make_pair(key,code));
pcode=ccode;
}
}
out_str=oss.str();
return mp;
}
下面的代码是对上面压缩与解压缩的测试,包括测试压缩然后再解压缩得到的字符串与原字符串是否相等,压缩与解压所构造的字典是否一致,并给出了字典。
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
#include <map>
#include < string>
#include <sstream>
#include <cstdlib>
using namespace std;
const string letters( " ab "); // cdefghijklmnopqrstuvwxyz");
const int Alpha= 2;
template < class T>
void con_print(T& c){
typename T::iterator ite;
for(ite=c.begin();ite!=c.end();++ite){
cout<<*ite<< ' ';
}
cout<<endl;
}
template < class K, class E>
void map_print(map<K,E>& mp){
typename map<K,E>::iterator ite;
for(ite=mp.begin();ite!=mp.end();++ite)
cout<< " < "<<ite->first<< " , "<<ite->second<< " > "<< ' ';
cout<<endl;
}
map< string,unsigned> compress( string & in_str, string& str_code){
map< string,unsigned> mp;
int N=Alpha;
int used=N;
for( int i= 0;i<N;i++){
string key( 1, ' a '+i);
unsigned code=i;
mp.insert(pair< string,unsigned>(key,code));
}
typename map< string,unsigned>::iterator ite;
ostringstream oss;
size_t len=in_str.length();
if(len< 2){
ite=mp.find(in_str.substr( 0, 1));
oss<<ite->second;
}
else{
string pcode;
pcode+=in_str[ 0];
for( int i= 1;i<len;i++){
char c=in_str[i];
string key=pcode+c;
ite=mp.find(key);
if(ite!=mp.end()){
pcode=key;
}
else{
oss<<mp[pcode];
mp.insert(pair< string,unsigned>(key,used++));
pcode=c;
}
}
oss<<mp[pcode];
}
str_code=oss.str();
return mp;
}
map<unsigned, string> decomp( string& str_code, string& out_str){
map<unsigned, string> mp;
int N=Alpha;
unsigned used=N;
for( int i= 0;i<N;i++){
unsigned key=i;
string code( 1, ' a '+i);
mp.insert(make_pair(key,code));
}
typename map<unsigned, string>::iterator ite;
ostringstream oss;
size_t len=str_code.length();
if(len< 2){
oss<<mp[(unsigned)(str_code[ 0]- ' 0 ')];
}
else{
unsigned pcode=(unsigned)(str_code[ 0]- ' 0 ');
oss<<mp[pcode];
for( int i= 1;i<len;i++){
string prefix=mp[pcode];
char surfix;
string code;
unsigned key=used++;
unsigned ccode=(unsigned)(str_code[i]- ' 0 ');
ite=mp.find(ccode);
if(ite!=mp.end()){
oss<<ite->second;
surfix=(ite->second).at( 0);
code=prefix+surfix;
// unsigned key=used++;
// mp.insert(make_pair(key,code));
}
else{
// string prefix=mp[pcode];
surfix=prefix[ 0];
code=prefix+surfix;
// unsigned key=used++;
oss<<code;
}
mp.insert(make_pair(key,code));
pcode=ccode;
}
}
out_str=oss.str();
return mp;
}
bool map_equal(map< string,unsigned>& mp,map<unsigned, string>& mp2){
typename map< string,unsigned>::iterator ite;
typename map<unsigned, string>::iterator ite2;
for(ite=mp.begin();ite!=mp.end();++ite){
ite2=mp2.find(ite->second);
if(ite->first!=ite2->second)
return false;
}
return true;
}
int main1(){
string in_str( " aaabbbbbbaabaaba ");
string str_code;
map< string,unsigned> mp=compress(in_str,str_code);
cout<<in_str<< " : "<<str_code<<endl;
map_print(mp);
return 0;
}
int main2(){
string str_code( " 0214537 ");
string out_str;
map<unsigned, string> mp=decomp(str_code,out_str);
cout<<str_code<< " : "<<out_str<<endl;
map_print(mp);
return 0;
}
int main(){
int N= 15;
for( int i= 0;i< 50;i++){
string in_str(N, ' ');
for( int j= 0;j<N;j++)
in_str[j]=letters[rand()% 2];
string str_code;
map< string,unsigned> mp=compress(in_str,str_code);
string out_str;
map<unsigned, string> mp2=decomp(str_code,out_str);
cout<<in_str<< " ";
cout<<str_code<< " ";
cout<<out_str<< " ";
if(in_str==out_str)
cout<< " OK ";
else
cout<< " NO ";
if(map_equal(mp,mp2))
cout<< " OK ";
else
cout<< " NO ";
map_print(mp2);
}
}
下面是一个测试结果示例:
这儿存在的一个问题是:字符串不要太长,不然如果之巅长度超过10以后编码就乱了,因为编码之后的数字之间是没有空格进行分隔的。解决方法是可以换一种编码方式,可以采用大写字母。
上面的截图中也出现了字典长度超过10的情况,但是压缩和解压的结果仍然一致,原因是因为最后一个映射没有用到。