串、二叉树、图

1、串(string)是由零个或多个字符组成的有限序列,零个字符的串称为空串(null string),可直接用“”表示。
2、空格串:只包含空格的串,空格串有长度。

3、串中任意个数的连续字符组组成的子序列称为该串的子串,包含子串的串称为主串。

4、子串在主串中的位置就是子串的第一个字符在主串中的序号。

5、串的顺序存储结构是用一组地址连续的存储单元存储字符序列。

//朴素的模式匹配算法(串的定位操作通常称作串的模式匹配)
  //对主串的每一个字符作为子串的开头,与要匹配的字符串进行匹配 
  //对主串做大循环,每个字符开头做T的长度小循环,直到匹配成功或完全遍历
   //用基本数组实现
   //返回子串在主串第pos个字符之后的位置,若不存在则返回0
   int Index(String S,String T,int pos)
   {
   	   int i=pos;//i用于主串S中当前位置下标,若pos不为1则从pos位置开始匹配
	   int j=1;//j用于子串中当前位置下标值
	   while(i<S[0]&&j<T[0]) //字符串的长度存在S[0],T[0]中
	    {
	    	if(S[i]==T[j])//两字母相等则继续
			{
				i++;
				j++;
			}
			else//指针后退开始匹配 
			{
				i=i-j+2;//关键代码,退回到上次匹配首位的下一位
				j=1;//j退回到子串T的首位 
			} 
		}
		if(j>T[0])
		  return i-T[0];
		else
		  return 0;  
	} 
//KMP模式匹配算法实现 
//通过计算返回子串T的next数组
void get_next(String T,int *next)
{
	int i,j;
	i=1;
	j=0;
	nextval[1]=0;
	while(i<T[0])//此处T[0]表示串T的长度
	{
		if(j==0||T[i]==T[j])//T[i]表示后缀的单个字符,T[j] 表示前缀的单个字符
		{
			++i;
			++j;
			if(T[i]!=T[j])//若当前字符与前缀字符不同
			   nextval[i]=j;//当前j为nextval在i位置饿值
			else 
			   nextval[i]=nextval[j];
			    
		 } 
		 else
		   j=next[j];//如果字符不同,则j值回溯 
	 } 
	
 } 

二叉树

二叉树(Binary Tree)是n(n>=0)个结点的有限集合,该集合或者为空集(称为空二叉树),或者由一个根节点和两棵互不相交的、分别称为根结点的左子树和右子树的二叉树组成。

二叉树的遍历

二叉树的遍历(traversing binary tree)是指从根结点出发,按照某种次序依次访问二叉树中所有结点,使得每个结点被访问且仅被访问依次。

//二叉树的定义
	 //折半查找算法 
	 //二叉树的二叉链表结点结构定义
	 typedef struct BiTNode//结点结构 
	 {
	 	TElemType data;//结点数据
		struct BiTNode *lchild,*rchild;//左右孩子指针
	  }BiTNode,*BiTree; 
	  //前序遍历算法  递归
	   void PreOrderTraverse(BiTree T)
	   {
	   	if(T==NULL)
	   	  return ;
	   	printf("%c",T->data);//显示结点数据,可以更改为其他对结点的擦操作
		PreOrderTraverse(T->lchild);//先遍历左子树
		PreOrderTraverse(T->rchild);//最后遍历右子树 
		} 
	//中序遍历算法 递归
	void InOrderTraverse(BiTree T)
	{
		if(T==NULL)
		  return ;
		  InOrderTraverse(T->lchild);//中序遍历子树
		  printf("%c",T->data);//显示结点数据,可以更改为其他对结点操作
		  InOederTraverse(T->rchild);//最后中序遍历右子树 
	 }
	 void InOrderTraverse(BiTree T)
	 {
	 	if(T==NULL)
	 		return ;
	 		InOrderTraverse(T->lchild);
	 		printf("%c",T->data);//显示结点数据
			InOrderTraverse(T->rchild);
	  }
	//后序遍历算法
	void PostOrderTraverse(BiTree T)
	{
		if(T==NULL)
		 return ;
		 PostOrderTraverse(T->lchild);//先后序遍历左子树
		 PostOrderTraverse(T->rchild);//再遍历右子树
		 printf("%c",T->data); 
	 }
	 //二叉树的建立,按前序输入二叉树中结点的值
	 //#表示空数,构造二叉树链表表示二叉树T
	 void CreatBiTree (BiTree T)
	 {
	 	TElemType ch;
	 	scanf("%c",ch);
	 	if(ch=='#')
	 	  *T=NULL;
	 	else 
	 	 {
	 	 	*T=(BiTree)malloc(sizeof(BiTNode));
	 	 	if(!*T)
	 	 	  exit(OVERFLOW);
	 	 	(*T)->data=ch;//生成根结点
			 CreateBiTree(&(*T)->lchild);//构造左子树
			 CreateBiTree(&(*T)->rchild);//构造右子树 
		  }
	  } 

图(Graph)是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为:G(V,E),其中,G表示一个圆,V是图G中顶点的集合,E是图G中边的集合。

从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这一过程就叫做图的遍历(Traversing Graph。

深度优先遍历

深度优先遍历(Depth_First_Search)深度优先搜索,简称DFS

//邻接矩阵的深度优先递归算法
void DFS(MGraph G,int i)
{
	int j;
	visited[i]=TRUE;
	printf("%c",G.vexs[i]);//打印顶点,也可以是其他操作
	for(j=0;j<G.numVertexes;j++)
	    if(G.arc[i][j]==1&&!visited[j])
	       DFS(G,j);//对访问的邻接顶点递归调用
		    
}
//邻接矩阵的深度遍历操作
void DFSTraverse(MGraph G)
{
	int i;
	for(i=0;i<G.numVertexes;i++)
      visited[i]=FALSE;//初始所有顶点状态都是未访问过状态
	for(i=0;i<G.numVertexes;i++)
	    if(!visited[i])//对未访问过的顶点调用DFS,若是连通图,只会执行一次
		  DFS(G,i);
}
//邻接表的深度优先递归算法
void DFS(GraphAdjList GL,int i)
{
	EdgeNode *p;
	visited[i]=TRUE;
	printf("%c",GL->adjList[i].data);//打印顶点,也可是其他操作
	p=GL->adjList[i].firstedge;
	while(p)
	{
		if(!visited[p->adjvex])
		   DFS(GL,p->adjvex);//对未访问的邻结顶点递归调用
		p=p->next;    
	} 
}
//邻接表的深度遍历搜索
void DFSTraverse(GraphAdjList GL)
{
	int i;
	for(i=0;i<GL->numVertexes;i++)
	    visited[i]=FALSE;//将所有的顶点状态都是未访问过的状态
		for(i=0;i<GL->numVertexes;i++)
		    if(!visited[i])//对未访问过的顶点调用DFS,若是连通图,只会执行一次
			   DFS(GL,i); 
}

广度优先遍历

广度优先遍历(Breath_First_Search)广度优先搜索,简称BFS

//邻接矩阵的广度遍历算法
void BFSTraverse(MGraph G)
{
	int i,j;
	Queue Q;
	for(i=0;i<G.numVertexes;i++)
	    visited[i]=FALSE;
	    InitQueue(&Q);//初始化一辅助用的队列
	for(i=0;i<G.numVertexes;i++)//对每一个顶点做循环
	{
		if(!visited[i])//若是未访问过就处理
		{
			visited[i]=TRUE;//设置当前顶点访问过
		    printf("%c",G.vexs[i]);//打印顶点,也可以其他操作
			EnQueue(&Q,i);//将此顶点入队列
			while(!QueueEmpty(Q))//若当前队列不为空
			{
				
	            DeQueue(&Q,&i);//将队中元素出队列,赋值给i
	            for(j=0;j<G.numVertexes;j++)
	            {
	            	//判断其他顶点若与当前顶点存在边且未访问过
					if(G.arc[i][j]==1&&!visited[j])
					{
						visited[j]=TRUE;//找到此顶点标记为已访问
						printf("%c",G.vexs[j]);//打印顶点
						EnQueue(&Q,j);//将找到的此顶点入队列 
					} 
					 
				}
		 } 
	}
	 
	  
 }	    
 }
 //邻接表的广度遍历算法
 void BFSTraverse(GraphAdjList GL)
 {
 	int i;
 	EdgeNode *p;
 	Queue Q;
 	for(i=0;i<GL->numVertexes;i++)
 	    visited[i]=FALSE;
 	InitQueue(&Q)
	 for(i=0;i<GL->numVertexes;i++)
	 {
	 	if(!visited[i])
	 	{
	 		visited[i]=TRUE;
	 		printf("%c",GL->adjList[i].data);//打印顶点
			EnQueue(&Q,i);
			while(!QueueEmpty(Q))
			{
				DeQueue(&Q,i);
				p=GL->adjList[i].firstedge;//找到当前顶点
				while(p)
				{
					if(!visited[p->adjvex])//若此点未被访问
					{
						visited[p->adjvex]=TRUE;
						printf("%c",GL->adjList[p->adjvax].data);
						EnQueue(&Q,p->adjvex);//将此点入队列 
					}
					p=p->next;//指针指向另一个邻接点 
					 
				} 
			}
			  
		 }
     }    
 } 

最小生成树

构造连通网的最小代价生成树称为最小生成树

普利姆(Prim)算法
//普利姆(Prim算法)
void MiniSPanTree_Prim(MGrph G)
{
	int main,i,j,k;
	int adjvex[MAXVEX];//保存相关顶点下标
	int lowcoast[MAXVEX];//保存相关顶点间边的权值
	lowcost[0]=0;//初始化第一个权值为0,即v0加入生成树
	//lowcost的值为0,在这里就是此下标的顶点已经加入生成树
	adjvex[0]=0;//初始化第一个顶点下标为0
	for(i=1;i<G.numVertexes;i++)//循环除下标为0外的全部顶点
	{
		lowcost[i]=G.arc[0][i];//将v0顶点与之有边的权值存入数组
		adjvex[i]=0;//初始化都为v0的下标 
	}
	for(i=1;i<G.numVertexes;i++)
	{
		min=INFINITY;//初始化最小权值
		//通常设置为不可能的大数字
		j=1;k=0;
		while(j<G.numVertexes)//循环全部点
		{
			if(lowcost[j]!=0&&lowcost[j]<min)
			 {//如果权值不为0且权值小于min
			      min=lowcost[j];//让当前权值成为最小值
				  k=j;//将当前最小值的下标存入k
				    
			 }
			 j++; 
		}
		printf("(%d,%d)",adjvex[k],k)//打印当前顶点边中权值最小边
		lowcost[k]=0;//将当前顶点权值设置为0,表示此顶点已经完成为任务
		for(j=1;j<G.numVertexes;j++)
		{
			if(lowcost[j]!=0&&G.arc[k][j]<lowcost[j])
			{
				//若下标为k的顶点各边权值小于此前这些未被加入生成树权值
				lowcost[j]=G.arc[k][j];//将较小权值存入lowcost
				adjvex[j]=k;//将下标为k的顶点存入adjvex 
			}
		 } 
	 } 	 
}
克鲁斯卡尔算法
//克鲁斯卡尔(Kruskal算法) 
void MiniSpanTree_Kruskal(MGraph G)//生成最小生成树
{
	int i,n,m;
	Edge edges[MAXEDGE];//定义边集数组
	int parent[MAXVEX]; //定义一维数组用来判断边与边是否形成环路
	//省略将邻接矩阵G转化为边集数组edges并按权值由小到大排序代码
	for(i=0;i<G.numVertexes;i++)
	    parent[i]=0;//初始化数组值为0
    for(i=0;i<G.numEdges;i++)
	    {
	    	n=Find(parent,edges[i].begin);
			m=Find(parent,edges[i].end);
			if(n!=m)//若n与m不相等,说明此边没有与现成生成树形成的 环路
			{
				parent[n]=m;//将此边的结尾顶点放入下边为起点的parent中
				//表示此顶点已经在生成树集合中
				printf("(%d,%d) %d",edges[i].begin,edges[i].end,edges[i].weight);
			 } 
		}
 } 
 int Find(int *parent,int f)//查找连线顶点的尾部下标
 {
 	while(parent[f]>0)
 	     f=parent[f];
    return f;
  } 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值