数据结构,算法与应用(2)

第5章 堆栈
堆栈是一个后进先出(last-in-first-out, LIFO)的数据结构。
1. 数组实现的堆栈
源代码如下:
复制代码
#include <iostream>
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;
    }
}
                                                      
复制代码
2.链表实现的堆栈
源代码如下:
复制代码
#include <iostream>
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;
    }
}
复制代码
3. 堆栈使用
(1)括号匹配
复制代码
#include <iostream>
#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);
}
复制代码
(2)汉诺塔
复制代码
#include <iostream>
#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);

}
复制代码

网上给出的一个很不错的非递归方式的汉诺塔实现,具体见这,下面是代码:

复制代码
#include <iostream>
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对上面的代码进行了一下修改:

复制代码
class Tower{
     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;
            }
        }
    }
}
复制代码

下图是对两种方法(递归和迭代)的比较:

 

上图给出的是4个盘的情况,对比可以发现,两种方法移动盘的步骤是一样的。  

 

(3)火车车厢重排

复制代码
// using stack
#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] = { 0369247185};
    cout <<  " Input permutation is 0369247185 " << endl;
    Railroad(p, 9, 3);
}
复制代码

(4)开关盒布线

复制代码
#include <iostream>
#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)离线等价类

复制代码
#include <iostream>
#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< boolout(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)迷宫老鼠

复制代码
#include <iostream>
#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. 公式化实现队列
实现代码:

复制代码
#include <iostream>
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. 链表描述
实现代码:

复制代码
#include <iostream>
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)火车重排

复制代码
// using queue
#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] = { 0369247185};
    cout <<  " Input permutation is 0369247185 " << endl;
    Railroad(p, 9, 3);
}
复制代码

不使用队列的实现:

复制代码
// with LIFO tracks
// 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] = { 0369247185};
    cout <<  " Input permutation is 0369247185 " << endl;
    Railroad(p, 9, 3);
}
复制代码

(2)电路布线

复制代码
#include <iostream>
#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);
}
复制代码

布线路图:

 

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)识别图元

复制代码
#include <iostream>
#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

程序输出: 

第7章 跳表和散列
1. 线性表来实现字典,该线性表按关键字从左到右依次增大。
复制代码
#include <iostream>
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&  outconst;
     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&  outconst
{
    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< intint> 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;
}
复制代码
2. 跳表描述
(1)理想情况
(2)插入删除
(3)级的分配
(4)复杂性

跳表的实现代码:

复制代码
#if 1
#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< intlong> S( 100011000.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
复制代码
3. 散列表描述/哈希表
(1)线性开型寻址
复制代码
#include <iostream>
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< intlong> 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)链表散列

复制代码
#include <iostream>
#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> 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;
}
复制代码

  LZW解压缩  

解压缩代码:与压缩代码是对应的: 

复制代码
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;
}
复制代码

下面的代码是对上面压缩与解压缩的测试,包括测试压缩然后再解压缩得到的字符串与原字符串是否相等,压缩与解压所构造的字典是否一致,并给出了字典。 

复制代码
#include <iostream>
#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);
    }

}
复制代码

  下面是一个测试结果示例: 

每一个行中的两个OK表示字符串是否一致,字典是否一致。 最后的是字典。  

这儿存在的一个问题是:字符串不要太长,不然如果之巅长度超过10以后编码就乱了,因为编码之后的数字之间是没有空格进行分隔的。解决方法是可以换一种编码方式,可以采用大写字母。

上面的截图中也出现了字典长度超过10的情况,但是压缩和解压的结果仍然一致,原因是因为最后一个映射没有用到。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值