这篇文章是关于严蔚敏清华版《数据结构》教材的代码,包括书上大纲规定的线性表,链表,栈,队列,二叉树,图,排序,
查找等基本算法的编码,还包括循环链表,广义表,两栈共享空间,字符串模式匹配等非常规,较难数据结构的编码,除此之外书本
后面大量的思考题,例如约瑟夫环,括号匹配,迷宫问题,八皇后,火车厢重排,斐波那契查找等一些列经典问题也有代码。文章中
的代码,均已调试通过,并附有程序运行结果,读者可以自行复制运行。
这是我用一个假期重学数据结构的劳动结果,希望此篇文章,能给初学数据局结构的同学以帮助,代码若有什么问题,可以
直接用QQ与我联系,感谢赐教。
由于整个篇幅较长,相关内容按照数据结构课本章节内容组织。下面是第五章,其他章节请参照其他博客。
第五章 图
#include <iostream>
using namespace std;
const int MaxSize=10;
template <class T>
class MGraph
{
public:
MGraph(T a[],int n,int e);
~MGraph(){}
T GetVex(int i);
void PutVex(int i,T value);
void InsertVex(int i,T value);
void DeleteVex(int i);
void InsertArc(int i,int j);
void DeleteArc(int i,int j);
void DFSTraverse(int v);
void BFSTraverse(int v);
void Print();
private:
T vertex[MaxSize];
int arc[MaxSize][MaxSize];
int vertexNum,arcNum;
};
template <class T>
MGraph<T>::MGraph(T a[],int n,int e)
{
cout<<"***********无向图的初始化************"<<endl;
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++)
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)
for(int j=0;j<vertexNum;j++)
arc[i][j]=0;
int i1,j1;
for(i=0;i<arcNum;i++)
{
cout<<"^输入第"<<i+1<<"边依附的两个顶点的序号:";
cin>>i1>>j1;
arc[i1][j1]=1;
arc[j1][i1]=1;
cout<<endl;
}
}
template <class T>
T MGraph<T>::GetVex (int i)
{
cout<<"*********取第"<<i<<"个顶点的数据信息*********"<<endl;
return vertex[i-1];
}
template <class T>
void MGraph<T>::PutVex (int i,T value)
{
cout<<"*********第"<<i<<"个顶点的数据置为"<<value<<"*********"<<endl;
if(i>vertexNum)
throw"顶点不存在";
vertex[i-1]=value;
}
template <class T>
void MGraph<T>::InsertVex (int i,T value)
{
cout<<"*********插入一个编号为"<<i<<"数据域为"<<value<<"的顶点*********"<<endl;
for(int j=vertexNum;j>=i+1;j--)
vertex[j]=vertex[j-1];
vertex[j]=value;
int k;
for(j=vertexNum;j>=i+1;j--)//移动列
for(k=0;k<vertexNum;k++)
arc[k][j]=arc[k][j-1];
for(j=vertexNum;j>=i+1;j--)//移动行
for(k=0;k<=vertexNum;k++)
arc[j][k]=arc[j-1][k];
for(k=0;k<=vertexNum;k++)
{
arc[i][k]=0;//初始化第i行
arc[k][i]=0;//初始化第i列
}
vertexNum++;
int degree;
cout<<"输入该顶点的度数:";
cin>>degree;
arcNum=arcNum+degree;
cout<<"----输入此顶点与其它顶点的依附情况"<<endl;
int i1;
for(k=0;k<degree;k++)
{
cout<<"^输入第"<<k+1<<"个顶点与此顶点邻接的编号:";
cin>>i1;
arc[i][i1]=1;
arc[i1][i]=1;
cout<<endl;
}
}
template <class T>
void MGraph<T>::DeleteVex(int i)
{
cout<<"***********删除编号为"<<i<<"的顶点***********"<<endl;
for(int j=i;j<vertexNum-1;j++)
vertex[j]=vertex[j+1];
int k;
int degree=0;
for(k=0;k<vertexNum;k++)
{
if(arc[i][k]==1)
degree++;
}
for(j=i;j<vertexNum-1;j++)
for(k=0;k<vertexNum;k++)
arc[k][j]=arc[k][j+1];
for(j=i;j<vertexNum-1;j++)
for(k=0;k<vertexNum;k++)
arc[j][k]=arc[j+1][k];
vertexNum--;
arcNum=arcNum-degree;
}
template <class T>
void MGraph<T>::InsertArc(int i,int j)
{
cout<<"**********插入一条边**********"<<endl;
arc[i][j]=1;
arc[j][i]=1;
arcNum++;
}
template <class T>
void MGraph<T>::DeleteArc(int i,int j)
{
cout<<"**********删除一条边**********"<<endl;
arc[i][j]=0;
arc[j][i]=0;
arcNum--;
}
int D_visited[MaxSize]={0};
template <class T>
void MGraph<T>::DFSTraverse(int v)
{
cout<<vertex[v]<<" ";
D_visited[v]=1;
for(int j=0;j<vertexNum;j++)
{
if(arc[v][j]==1 && D_visited[j]==0)
DFSTraverse(j);
}
}
template <class T>
void MGraph<T>::BFSTraverse(int v)
{
int B_visited[MaxSize]={0};
int front,rear;
front=rear=-1;
int Q[MaxSize];
cout<<vertex[v]<<" ";
B_visited[v]=1;
Q[++rear]=v;
while(front!=rear)
{
v=Q[++front];
for(int j=0;j<vertexNum;j++)
{
if(arc[v][j]==1 && B_visited[j]==0)
{
cout<<vertex[j]<<" ";
B_visited[j]=1;
Q[++rear]=j;
}
}
}
}
template <class T>
void MGraph<T>::Print ()
{
cout<<"**********输出无向图的存储情况**********"<<endl;
cout<<"打印无向图顶点数组:";
for(int i=0;i<vertexNum;i++)
cout<<vertex[i]<<" ";
cout<<endl;
cout<<"打印无向图的存储矩阵:"<<endl;
cout<<" "<<vertex[0]<<" ";
for( i=1;i<vertexNum;i++)
cout<<vertex[i]<<" ";
cout<<endl;
for(i=0;i<vertexNum;i++)
{
cout<<vertex[i]<<" ";
for(int j=0;j<vertexNum;j++)
cout<<arc[i][j]<<" ";
cout<<endl;
}
}
void main()
{
cout<<"************关于无向图的操作**************"<<endl;
char A[5]={'A','B','C','D','E'};
MGraph<char> Mg(A,5,5);
Mg.Print();
cout<<Mg.GetVex(2)<<endl;
Mg.InsertVex(2,'F');
Mg.Print();
Mg.DeleteVex(2);
Mg.Print();
cout<<"**********深度优先遍历***********"<<endl;
Mg.DFSTraverse(0);
cout<<endl<<"**********广度优先遍历***********"<<endl;
Mg.BFSTraverse(0);
cout<<endl;
}
#include <iostream>
using namespace std;
const int MaxSize=10;
struct ArcNode
{
int adjvex;
ArcNode *next;
};
template <class T>
struct VertexNode
{
T vertex;
ArcNode *firstedge;
};
template <class T>
class ALGraph
{
private:
VertexNode<T> adjlist[MaxSize];
int vertexNum,arcNum;
public:
ALGraph(T a[],int n,int e);
~ALGraph();
T GetVex(int i);
void PutVex(int i,T value);
void InsertVex(int i,T value);
void DeleteVex(int i);
void InsertArc(int i,int j);
void DeleteArc(int i,int j);
void DFSTraverse(int v);
void BFSTraverse(int v);
void Print();
};
template <class T>
ALGraph<T>::ALGraph(T a[],int n,int e)
{
cout<<endl<<"***********初始化无向图***********"<<endl;
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++)
{
adjlist[i].vertex=a[i];
adjlist[i].firstedge=NULL;
}
int i1,j1;
ArcNode *s1,*s2;
for(int k=0;k<arcNum;k++)
{
cout<<"^输入第"<<k+1<<"条边所依附的两个顶点的编号:";
cin>>i1>>j1;//注意无向图每输入一条表要向两个边表中插入节点
s1=new ArcNode;
s1->adjvex=j1;
s1->next=adjlist[i1].firstedge;
adjlist[i1].firstedge=s1;
s2=new ArcNode;
s2->adjvex=i1;
s2->next=adjlist[j1].firstedge;
adjlist[j1].firstedge=s2;
}
}
template <class T>
ALGraph<T>::~ALGraph()
{
ArcNode *p,*q;
for(int i=0;i<vertexNum;i++)//共需要释放vertexNum个没有头结点的链表所占的空间
{
p=adjlist[i].firstedge;
while(p)
{
q=p;
p=p->next;
delete q;
}
adjlist[i].firstedge=NULL;
}
}
template <class T>
T ALGraph<T>::GetVex (int i)
{
cout<<"*********取第"<<i<<"个顶点的数据信息*********"<<endl;
return this->adjlist[i-1].vertex;
}
template <class T>
void ALGraph<T>::PutVex (int i,T value)
{
cout<<"*********第"<<i<<"个顶点的数据置为"<<value<<"*********"<<endl;
if(i>vertexNum)
throw"顶点不存在";
this->adjlist[i-1].vertex=value;
}
template <class T>
void ALGraph<T>::InsertVex (int i,T value)
{
cout<<"*********插入一个编号为"<<i<<"数据域为"<<value<<"的顶点*********"<<endl;
//修改顶点表
adjlist[vertexNum].firstedge=NULL;
for(int j=vertexNum;j>=i+1;j--)
{
adjlist[j].vertex=adjlist[j-1].vertex;
adjlist[j].firstedge=adjlist[j-1].firstedge;
}
adjlist[j].vertex=value;
adjlist[j].firstedge=NULL;
//*****************************//过渡工作
ArcNode *p;
for(j=0;j<=vertexNum;j++)
{
p=adjlist[j].firstedge;
while(p)
{
if(p->adjvex>=i)//但凡原来编号大于等于i的边表中编号自增1
p->adjvex++;
p=p->next;
}
}
//*****************************
//修改边表
int degree;
cout<<"输入新插入顶点的度数:";
cin>>degree;
int i1;
ArcNode *s1,*s2;
for(j=0;j<degree;j++)
{
cout<<"^输入第"<<j+1<<"个邻接顶点的编号:";
cin>>i1;
s1=new ArcNode;
s1->adjvex=i1;
s1->next=adjlist[i].firstedge;
adjlist[i].firstedge=s1;
s2=new ArcNode;
s2->adjvex=i;
s2->next=adjlist[i1].firstedge;
adjlist[i1].firstedge=s2;
}
//收尾工作
vertexNum++;
arcNum=arcNum+degree;
}
template <class T>
void ALGraph<T>::DeleteVex(int i)
{
cout<<"***********删除编号为"<<i<<"的顶点***********"<<endl;
ArcNode *p,*q;
int degree=0;
p=adjlist[i].firstedge;
while(p)
{
q=p;
degree++;
p=p->next;
delete q;
}
adjlist[i].firstedge=NULL;
for(int j=i;j<vertexNum-1;j++)
{
adjlist[j].vertex=adjlist[j+1].vertex;
adjlist[j].firstedge=adjlist[j+1].firstedge;
}
ArcNode *p2,*pre;
for(j=0;j<vertexNum-1;j++)
{
p2=pre=adjlist[j].firstedge;
while(p2)
{
if(p2->adjvex==i)
{
if(p2==adjlist[j].firstedge)
adjlist[j].firstedge=p2->next;
else
pre->next=p2->next;
break;
}
pre=p2;
p2=p2->next;
}
}
//*****************************//过渡工作(与插入节点比较:注意代码位置)
ArcNode *p1;
for(j=0;j<vertexNum-1;j++)
{
p1=adjlist[j].firstedge;
while(p1)
{
if(p1->adjvex>i)//但凡原来编号大于等于i的边表中编号自增1
p1->adjvex--;
p1=p1->next;
}
}
//*****************************
vertexNum--;
arcNum=arcNum-degree;
}
template <class T>
void ALGraph<T>::InsertArc(int i,int j)
{
cout<<"**********插入一条边**********"<<endl;
ArcNode *s1,*s2;
s1=new ArcNode;
s1->adjvex=j;
s1->next=adjlist[i].firstedge;
adjlist[i].firstedge=s1;
s2=new ArcNode;
s2->adjvex=i;
s2->next=adjlist[j].firstedge;
adjlist[j].firstedge=s2;
arcNum++;
}
template <class T>
void ALGraph<T>::DeleteArc(int i,int j)
{
cout<<"**********删除一条边**********"<<endl;
ArcNode *p,*pre;
p=adjlist[i].firstedge;
while(p)
{
if(p->adjvex==j)
{
if(p==adjlist[i].firstedge)
adjlist[i].firstedge=p->next;
else
pre->next=p->next;
break;
}
pre=p;
p=p->next;
}
p=adjlist[j].firstedge;
while(p)
{
if(p->adjvex==i)
{
if(p==adjlist[j].firstedge)
adjlist[j].firstedge=p->next;
else
pre->next=p->next;
break;
}
pre=p;
p=p->next;
}
arcNum--;
}
template <class T>
void ALGraph<T>::Print ()
{
cout<<"********打印邻接表存储无向图的存储情况********"<<endl;
cout<<"打印顶点表:";
for(int i=0;i<vertexNum;i++)
cout<<adjlist[i].vertex<<" ";
cout<<endl;
cout<<"打印边表:"<<endl;
ArcNode *p;
for(i=0;i<vertexNum;i++)
{
cout<<" --边表"<<i+1<<":("<<adjlist[i].vertex<<") ";
p=adjlist[i].firstedge;
while(p)
{
cout<<adjlist[p->adjvex].vertex<<" ";
p=p->next;
}
cout<<endl;
}
cout<<endl;
}
int D_visited[MaxSize]={0};
template <class T>
void ALGraph<T>::DFSTraverse(int v)
{
cout<<adjlist[v].vertex<<" ";
D_visited[v]=1;
ArcNode *p;
int j;
p=adjlist[v].firstedge;
while(p)
{
j=p->adjvex;
if(D_visited[j]==0)
DFSTraverse(j);
p=p->next;
}
}
int B_visited[MaxSize]={0};
template <class T>
void ALGraph<T>::BFSTraverse(int v)
{
int front,rear;
int Q[MaxSize];
front=rear=-1;
cout<<adjlist[v].vertex<<" ";
B_visited[v]=1;
Q[++rear]=v;
ArcNode *p;
int j;
while(front!=rear)
{
v=Q[++front];
p=adjlist[v].firstedge;
while(p)
{
j=p->adjvex;
if(B_visited[j]==0)
{
cout<<adjlist[j].vertex<<" ";
B_visited[j]=1;
Q[++rear]=j;
}
p=p->next;
}
}
}
void main()
{
cout<<"***********无向图(邻接表)的操作***************"<<endl;
char Vertex[5]={'A','B','C','D','E'};
ALGraph<char> ALg(Vertex,5,5);
ALg.Print();
ALg.InsertVex(2,'F');
ALg.Print();
ALg.DeleteVex(2);
ALg.Print();
ALg.InsertArc(0,2);
ALg.Print();
ALg.DeleteArc(0,2);
ALg.Print();
cout<<"***********深度优先遍历***********"<<endl;
ALg.DFSTraverse(0);
cout<<endl;
cout<<"***********广度优先遍历************"<<endl;
ALg.BFSTraverse(0);
cout<<endl;
}
普里姆算法求最小生成树
#include <iostream>
using namespace std;
const int MaxSize=10;
const int inf=10000;
template <class T>
class MGraph
{
public:
MGraph(T a[],int n,int e);
~MGraph(){}
friend void Prim(MGraph<T> G);
private:
T vertex[MaxSize];
int arc[MaxSize][MaxSize];
int vertexNum,arcNum;
};
template <class T>
MGraph<T>::MGraph(T a[],int n,int e)
{
cout<<"**************无向网图的初始化***************"<<endl;
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++)
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)
for(int j=0;j<vertexNum;j++)
{
if(i==j)
arc[i][j]=0;
else
arc[i][j]=inf;
}
int i1,j1,length;
for(i=0;i<arcNum;i++)
{
cout<<"^输入第"<<i+1<<"边依附的两个顶点的序号及该边的长度:";
cin>>i1>>j1>>length;
arc[i1][j1]=length;
arc[j1][i1]=length;
}
}
int adjvex[MaxSize];
int MinEdge(int LowCost[],int Num)
{
int k=1;
int FlagValue=LowCost[1];
for(int i=2;i<Num;i++)
{
if(LowCost[i]<FlagValue && LowCost[i]!=0)//特别注意此处条件
{
FlagValue=LowCost[i];
k=i;
}
}
return k;
}
template <class T>
void Prim(MGraph<T> G)//特别注意此处的写法
{
cout<<"**********求无向网图的最小生成树***********"<<endl;
int lowcost[MaxSize];
for(int i=1;i<G.vertexNum;i++)
{
lowcost[i]=G.arc[0][i];
adjvex[i]=0;
}
lowcost[0]=0;
int k;
for(i=1;i<G.vertexNum;i++)
{
k=MinEdge(lowcost,G.vertexNum);//需要定义查找最小值的函数
cout<<"("<<G.vertex[k]<<G.vertex[adjvex[k]]<<")"<<lowcost[k]<<" ";
lowcost[k]=0;
for(int j=1;j<G.vertexNum;j++)
{
if(G.arc[k][j]<lowcost[j])
{
lowcost[j]=G.arc[k][j];
adjvex[j]=k;
}
}
}
cout<<endl;
}
void main()
{
cout<<"************关于无向图的操作**************"<<endl;
char A[6]={'A','B','C','D','E','F'};
MGraph<char> Mg(A,6,9);
cout<<endl;
Prim(Mg);
}
小程序大陷阱
#include <iostream>
using namespace std;
#include <string>
void main()
{
char Ch1[6]={'A','B','C','D','E','\0'};
cout<<Ch1<<endl;
char Ch2[5]={'A','B','C','D','E'};
cout<<Ch2<<endl;
string s="123";
s=s+'A';
cout<<s<<endl;
string s2;
s2=s2+'b';
cout<<s2<<endl;
}
Dijkstra算法求单源点最短路径
#include <iostream>
using namespace std;
#include <string>
const int MaxSize=10;
const int inf=10000;
template <class T>
class MGraph
{
public:
MGraph(T a[],int n,int e);
~MGraph(){}
void Print();
friend void Dijkstra(MGraph<T> M,int v);
private:
T vertex[MaxSize];
int arc[MaxSize][MaxSize];
int vertexNum,arcNum;
};
template <class T>
MGraph<T>::MGraph(T a[],int n,int e)
{
cout<<"**************有向网图的初始化***************"<<endl;
vertexNum=n;
arcNum=e;
for(int i=0;i<vertexNum;i++)
vertex[i]=a[i];
for(i=0;i<vertexNum;i++)
for(int j=0;j<vertexNum;j++)
{
if(i==j)
arc[i][j]=0;
else
arc[i][j]=inf;
}
int i1,j1,length;
for(i=0;i<arcNum;i++)
{
cout<<"^输入第"<<i+1<<"边依附的两个顶点的序号及该边的长度:";
cin>>i1>>j1>>length;
arc[i1][j1]=length;
}
}
template <class T>
void MGraph<T>::Print ()
{
cout<<"**********输出有向图的存储情况**********"<<endl;
cout<<"打印有向图顶点数组:";
for(int i=0;i<vertexNum;i++)
cout<<vertex[i]<<" ";
cout<<endl;
cout<<"打印有向图的存储矩阵:"<<endl;
cout<<" "<<vertex[0]<<" ";
for( i=1;i<vertexNum;i++)
cout<<vertex[i]<<" ";
cout<<endl;
for(i=0;i<vertexNum;i++)
{
cout<<vertex[i]<<" ";
for(int j=0;j<vertexNum;j++)
cout<<arc[i][j]<<" ";
cout<<endl;
}
}
template <class T>
void Dijkstra(MGraph<T> M,int v)
{
cout<<"*********Dijkstra算法求单源点最短路径**********"<<endl;
int dist[MaxSize];
string path[MaxSize];
char s[MaxSize];
int i;
for(i=0;i<M.vertexNum;i++)
{
dist[i]=M.arc[v][i];
if(dist[i]!=inf)
{
path[i]="";
path[i]=path[i]+M.vertex[v]+M.vertex[i];
}
else
path[i]="";
}
cout<<endl;
s[0]=M.vertex[v];
dist[v]=0;
int num=1;
int k,j,InitValue;
while(num<M.vertexNum)
{
k=0;
InitValue=50000;//注意位置
for(i=0;i<M.vertexNum;i++)
{
if(dist[i]<InitValue && dist[i]!=0)
{
InitValue=dist[i];
k=i;
}
}
cout<<path[k]<<":"<<dist[k]<<" ";
s[num++]=M.vertex[k];
for(j=0;j<M.vertexNum;j++)
{
if(dist[j]>dist[k]+M.arc[k][j])
{
dist[j]=dist[k]+M.arc[k][j];
path[j]="";
path[j]=path[i]+path[k]+M.vertex[j];
}
}
dist[k]=0;//注意位置
cout<<endl;
}
cout<<endl<<endl;
}
void main()
{
cout<<"************关于有向图的操作**************"<<endl;
char A[5]={'A','B','C','D','E'};
MGraph<char> Mg(A,5,7);
cout<<endl;
Mg.Print();
Dijkstra(Mg,0);
}