排序
快速排序
-
选取pivot,左边放小的,右边放大的
int Partition(SqList& L,int low, int high){ L.r[0]=L.r[low]; pivotkey=L.r[low].key; while(low<high){ while(low<high&&L.r[high].key>=pivotkey) high--; L.r[low]=L.r[high]; while(low<high&&L.r[low].key<=pivotkey) low++; L.r[high]=L.r[low]; } L.r[low]=L.r[0]; return low; } void QSort(Sqlist& L,int low,int high){ if(low<high){ pivotloc = Partition(L,low,high); QSort(L,low,pivotloc-1); QSort(L,pivotloc+1,high); } }
循环队列
-
数据结构
typedef struct{ QElemType *base; int front,rear,tag; }SqQueue;
-
初始化队列
Status InitQueue(SqQueue &Q){ Q.base = (Q.QElemtype*)malloce(sizof(QElemType)*MAXQSIZE); Q.front = Q.rear = 0; return OK; }
-
入队
bool EnQueue(SqQueue &Q, QElemType e){ if(Q.tag==1&&Q.front==Q.rear) return ERROR; Q.base[rear] = e; Q.rear = (Q.rear +1) % MAXQSIZE; if(Q.tag==0) Q.tag=1; //非满->满 return OK; }
-
出队
bool DeQueue(SqQueue &Q, QElemType e){ if(Q.tag==0&&Q.front==Q.rear) return ERROR; e = Q.base[Q.front]; Q.front = (Q.front +1) % MAXQSIZE; if(Q.tag==1) Q.tag=0; //满->非满 return OK; }
树和二叉树
树
树的数据结构
-
双亲表示法
typedef struct PTNode{ TElemType data; int parent; }PTNode; typedef struct{ PTNode nodes[MAX_TREE_SIZE]; int r,n; //根的位置和结点数 }PTree;
-
孩子表示法
typedef struct CTNode{ int child; struct CTNode *next; }*ChildPtr; typedef struct{ TElemType data; ChildPtr firstchild; }CTBox; typedef struct{ CTBox nodes[MAX_TREE_SIZE]; int r,n; //根的位置和结点数 }CTree;
-
二叉链表示法
typedef struct CSNode{ Elem data; struct CSNode *firstchild, *nextsibling; } CSNode, *CSTree;
-
求树的深度
int TreeDepth(CSTree T){ if(!T) return 0; else{ h1 = TreeDepth(T->firstchild); h2 = TreeDepth(T->nextsibling); return (max(h1+1,h2)); } }
二叉树
性质:
- n 0 = n 2 + 1 n_0=n_2+1 n0=n2+1
- 完全二叉树深度 ⌊ l o g 2 n ⌋ + 1 \lfloor log_2{n}\rfloor+1 ⌊log2n⌋+1
顺序存储结构
#define MAX_TREE_SIZE 100 //二叉树的最大结点数
typedef TEleType SqBiTree[MAX_TREE_SIZE];
SqBiTree bt;
链式存储结构
-
二叉链表
typedef struct BiTNode{ TElemType data; struct BiNode *lchild, *rchild }BiTNode, *BiTree;
-
三叉链表
typedef struct TriTNode { // 结点结构 TElemType data; struct TriTNode *lchild, *rchild; // 左右孩子指针 struct TriTNode *parent; //双亲指针 } TriTNode, *TriTree;
-
双亲链表
data parent LRTag 保存的数据 双亲指针 左右孩子标志域 typedef struct BPTNode { // 结点结构 TElemType data; int *parent; // 指向双亲的指针 char LRTag; // 左、右孩子标志域 } BPTNode; typedef struct BPTree{ // 树结构 BPTNode nodes[MAX_TREE_SIZE]; int num_node; // 结点数目 int root; // 根结点的位置 } BPTree;
二叉树遍历操作
-
先序遍历
-
递归算法
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){ if(T){ if(Visit(T->data)) if(PreOrderTraverse(T->lchild,Visit)) if(PreOrderTraverse(T->rchild,Visit)) return OK; return ERROR; }else return OK; }
-
非递归算法
Status PreOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){ InitStack(S); Push(S,T); while(!StackEmpty(S)){ Pop(S,p);if(!Visit(p->data)) return ERROR; Push(S,p->rchild);Push(S,p->lchild);//因为栈是后进先出,所以先入右孩子 } return OK; }
-
-
中序遍历
-
递归算法
Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){ if(T){ if(InOrderTraverse(T->lchild, Visit)) if(Visit(T->data)) if(InOrderTraverse(T->rchild, Visit)) return OK; return ERROR; }else return OK }
-
非递归算法
Status InOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){ InitStack(S); Push(S,T); while(!StackEmpty(S)){ while(GetTop(S,p)&&p) Push(S,P->lchild); Pop(S,p); if(!StackEmpty(S)){ Pop(S,p); if(!Visit(p->data)) return ERROR; Push(S,p->rchild); } } return OK; }
-
-
层次遍历
Status LevelOrderTraverse(BiTree T, Status(*Visit)(TElemType e)){ InitQueue(Q); BiTree p; EnQueue(Q,T); while(!QueueEmpty(Q)){ Dequeue(Q,p); Visit(p); if(p->lchild!=NULL) EnQueue(Q,p->lchild); if(p->rchild!=NULL) EnQueue(Q,p->rchild); } }
-
求第k层上叶节点的数量
int LevelOrderTraverse(BiTree T,int k){ InitQueue(Q); BiTree p; EnQueue(Q,T); curWidth=0;depth=1;num=0; while(!QueueEmpty(Q)){ curWidth = QueueLenth(Q); for(v=0;v<curWidth;v++){ Dequeue(Q,p); if(depth==k&&p->lchild==NULL&&p->rchild==NULL) num++; if(p->lchild!=NULL) EnQueue(Q,p->lchild); if(p->rchild!=NULL) EnQueue(Q,p->rchild); } if(depth==k) break; else depth++; } return num; }
输出根到叶结点路径
void AllPath(Bitree T, Stack &S){
if(T){
Push(S,p->data);
if(!T->lchild&&!T->rchild) PrintStack(S);//左右子树都是空(叶节点)
else{
AllPath(T->lchild);
AllPath(T->rchild);
}
Pop(S);
}
}
求树的繁茂度(最大宽度*高度)
-
求最大宽度
int Width(BiTree T){ InitQueue(Q); BiTree p; EnQueue(Q,T); int maxWidth=0; int curWidth=0; while(!QueueEmpty(Q)){ curWidth = QueueLenth(Q); if(curWidth>maxWidth) maxWidth=curWidth; for(int i=0;i<curWidth;i++){ DeQueue(Q,p); if(p->lchild!=NULL) EnQueue(Q,p->lchild); if(p->rchild!=NULL) EnQueue(Q,p->rchild); } } }
-
求树的高度
int Height(BiTree T){ if(T==NULL) return 0; int l = Height(T->lchild); int r = Height(T->rchild); return l>r?l+1;r+1; }
线索二叉树
-
数据结构
typedef enum PointerTag{Link, Thread} ; typedef struct BiThrNod{ TElemType data; struct BiThrNode *lchild,*rchild; PointerTag LTag,Rtag; }BiThrNode,*BiThrTree;
-
中序线索化(带头节点)
void InThreading(BiThrTree p){ if(p){ InThreading(p->lchild); if(!p->lchild){ p->LTag = Thread; p->lchild = pre; } if(!pre->rchild){ pre->RTag = Thread; pre->rchild = p; } InThreading(p->rchild); } } Status InOrderThreading(BiThrTree &Thrt,BiThrTree T){ if(!(Thrt=(BiThrTree)malloc(sizeof(BiThrTree)))) exit(OVERFLOW); Thrt->LTag = Link; Thrt->RTag = Thread; Thrt->rchild = Thrt; if(!T) Thrt->lchild = Thrt; else{ Thrt->lchild = T; pre = Thrt; InThreading(T); pre->rchild = Thrt; pre->RTag = Thread; Thrt->rchild = pre; } return OK; }
-
中序遍历线索树(找到最左结点后一直往右走)(带头节点)
Status InOrderTraverse_Thr(BiThrTree T, Status(*Visit)(TElemType e)){ p = T->lchild; while(p!=T){ while(p->LTag = Link) p = p->lchild; if(!Visit(p->data)) return ERROR; while(p->RTag = Thread&&p->rchild!=T){ p = p->rchild; Visit(p->data); } p = p->rchild; } }
最小生成树
Prim算法
- 寻找局部最优解
- 每次将距离当前最小生成树最近的节点加入
- 适合稠密图
- 只与顶点数量相关
void MiniSpanTree_PRIM(MGraph G, VertexType u){
k = LocateVex(G,u);
for(j = 0;j<G.vexnum;++j)
if(j!=k) closedge[j] = {u, G.arcs[k][j].adj};
closedge[k].lowcost = 0;
for(i = 1;i<G.vexnum;++i){
k=minimum(closedge);
printf(closedge[k].adjvex, G.vexs[k]);
closedge[k].lowcost = 0;
for(j=0;j<G.vexnum;++j)
if(G.arcs[k][j].adj<closedge[j].lowcost)
closedge[j] = {G.vexs[k], G.arcs[k][j].adj};
}
}
无向图
深度优先搜索
- 基础算法
void DFSTraverse(Graph G,Status(*Visit)(int v)){
VisitFunc = Visit;
for(v=0;v<G.vexnum;v++) visited[v]=FALSE;
for(v=0;v<G.vexnum;v++){
if(!visited[v]){
visited[v]=TRUE;
DFS(G,v);
}
}
}
void DFS(Graph G, int v){
visited[v]=TRUE; VisitFunc(v);//访问结点
for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){
if(!visited[w]) DFS(G,w);
}
}
-
非递归
void DFS_Non_RC(AGraph& G, int v){ int w; InitStack(S); for(i=0;i<G.vexnum;i++){ //初始化标记数组 visited[i]=False; } Push(S,v); visited[v]=True; while(!IsEmpty(S)){ k=Pop(s); visit(k); for(w=FirstNeighbor(G, k);w>=0;w=NextNeighbor(G,k,w)){ if(!visited[w]){ Push(S,w); visited[w]=True; } } } }
-
查找路径 v → s v\to s v→s
void DFSearch(Graph G,int v,int s,char* PATH){ visited[v]=TRUE; Append(Path,getVertex(v)); for(w=FirstAdjVex(G,v);w>=0&&!found;w=NextAdjVex(G,v,w)){ if(w==s){found = TRUE;Append(Path,w)} else if(!visited[w]) DFSearch(G,w,s,PATH); } if(!found) Delete(PATH); }
-
判断是否有环
- 0:未访问
- 1:正在访问(在递归栈中)
- 2 :已经访问
int hasCycle(Graph* G) { for(v=0;v<G.vexnum;v++) visited[v]=FALSE; for(v = 0; v < G.vexnum; i++){ if(!visited[v]) if(DFS_hasCycle(G, v)) return 1; } return 0; } int DFS_hasCycle(Graph G, int v){ if(visited[v]==2) return FALSE; visited[v] = 1; for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){ if(DFS_hasCycle(G,w)) return TRUE; } visited[v] = 2; return FALSE; }
-
判断是否存在经过顶点 v v v的回路
bool dfs(Graph G, int v, int parent){ visited[v] = TRUE; Path[v] = TRUE; len++; for(w=FirstAdjVex(G,v);w>=0;w=NextAdjVex(G,v,w)){ if(!visited[w]){ if(dfs(G,w,v)) return TRUE; } else if(len>=3&&Path[w]&&w!= parent){return TRUE} } Path[v] = FALSE; return FALSE; } bool dfs(Graph G, int v, int s){ visited[v]=TRUE; len++; for(w=FirstAdjVex(G,v);w>=0&&!found;w=NextAdjVex(G,v,w)){ if(w==s&&len>=3) {found = TRUE; return TRUE;} else if(!visited[w]) dfs(G,w,s); } if(!found) return FALSE; }
广度优先搜索
-
基础算法
void BFSTraverse(Graph G,Status(*Visit)(int v)){ for(v=0;v<G.vexnum;v++) visited[v]=FALSE; InitQueue(Q); for(v=0;v<G.vexnum;v++){ visited[v]=TRUE; Visit(v); EnQueue(Q,v); while(!Empty(Q)){ DeQueue(Q,u); for(w = FirstAdjvex(u);w>=0;w = NextAdjvex(G,v,w)) if(!visited[w]){ visited[w]=TRUE; Visit(w); EnQueue(Q,u); } } } }
-
最短路径长度为k的节点
void FindPath(Graph G,int v,int k){ for(i=0;i<G.vexnum;i++) visited[i]=FALSE; InitQueue(Q); distance[v] = 0; visited[v] = TRUE; EnQueue(Q,v); while(!Empty(Q)){ DeQueue(Q,u); for(w = FirstAdjvex(G,v);w>=0;w = NextAdjvex(G,u,w)){ if(!visited[w]){ visited[w] = TRUE; distance[w] = distance[u] + 1; EnQueue(Q,w); } } } for(i=0;i<G.vexnum;i++){ if(distance[i]==k) printf(G.vertices[i]); } }
有向无环图及其应用
拓扑排序
-
每次选取入读为0的点进行输出
//邻接表储存 Status TopologicalSort(ALGraph G){ FindInDegree(G, indegree);//求各顶点的入度 InitStack(S); //初始化用于保存入度为0的栈 for(int i;i<G.vexnum;i++) { if(!indegree[i]) Push(S,i); //栈中加入入度为0的点 } count = 0;//已经输出的顶点数量 while(!StackEmpty(S)) { Pop(S,i); printf(i,G.vertices[i].data);//输出 ++count; for(p=G.vertices[i].firstarc;p;p=p->nexttarc) { k = p->adjvex; if(!(--indegree[k])) Push(S,k); } } if(count<G.vexnum) return ERROR; else return OK; } //不能进行拓扑排序则为有环
关键路径算法
-
ve(vertex-early)(顶点事件最早发生时间),更新取大:(前一个点+边)拓扑
-
vl(vertex-late)(顶点事件最晚发生时间),更新取小:(前一个点+边)逆拓扑
-
e(活动最早发生时间),即发出点的最早时间
-
l(活动最晚发生时间),即指向点的最晚 − - −边权
Status Toplogicalsort(ALGraph G,Stack &T){
FindInDegree(G,indegree);
InitStack(S);count=0;ve[0..G.vexnum-1]=0;
while(!StackEmpty(S))
{
Pop(S,j);Push(T,j);++count;
for(p=G.vertex[j].firstarc;p;p=p->nextarc)
{
k=p->adjvex;
if(!(--indegree[k])) Push(S,k);
if(ve[j]+*(p->weight)>ve[k]) ve[k]=ve[j]+*(p->weight);
}
}
if(count<G.vexnum) return ERROR;
else return OK;
}
void CriticalPath(ALGraph G)
{
if(!Toplogical(G,T)) return ERROR;
vl[0...G.vexnum-1]=ve[G.vexnum-1];
while(!StackEmpty(S))
{
Pop(S,j);
for(p=G.vertices[j];p;p=p->nextarc)
{
k = p->adjvex;dut = p->weight;
if(vl[k]-dut<vl[j]) vl[j]=vl[k]-dut;
}
for(j=0;j<G.vexnum;j++)
{
for(p=G.vertices[j];p;p=p->nextarc)
{
k = p->adjvex;det = p->weight;
ee = ve[j]; el=vl[k]-dut;
tag = ee==el?1:0;
printf(j,k,dut,ee,el,tag);
}
}
}
}