您的位置:首页 > 理论基础 > 数据结构算法

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

2015-09-14 16:36 330 查看
第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] = {0, 3, 6, 9, 2, 4, 7, 1, 8, 5};

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<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)迷宫老鼠



#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] = {0, 3, 6, 9, 2, 4, 7, 1, 8, 5};

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] = {0, 3, 6, 9, 2, 4, 7, 1, 8, 5};

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);

}

布线路图:

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



#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();

}

图元数据:

7

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& 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;

}

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<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

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<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)链表散列



#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的情况,但是压缩和解压的结果仍然一致,原因是因为最后一个映射没有用到。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: