字符串
找出一对相同字符在该字符串中最大距离
算法:用ASCII码(128个)作为数组的下标来支持随机访问,记录每个元素第一次出现的位置。然后依次访问string中的字符,并查看与ascii表中记录的第一次出现的位置做差,若差大于max,此为max
int getMaxLength(char str[],int n){
int max=0;
int ch[128];
for(int i=0;i<128;++i)ch[i]=-1;
for(int i=0;i<n;i++){
if(ch[str[i]]==-1) ch[str[i]]=i;
else{
if(i-ch[str[i]]>max) max=i-ch[str[i]];
}
}
return max;
}
顺序表
相对于单项链表,使用双向链表存储线性结构,可以提高查找速度(x)
错误:都是顺序查找,查找速度不变。
假设有序表的长度为n,则可以在1~n+1的位置上插入元素(x)
有序表插入的时候不能指定位置,因为这样就不再是有序表。
typedef struct{
ElemType data[MAXSIZE];int length;}SqL
链表
typedef struct LNode{
Elemtype data;struct LNode *next;}LinkList;
p,q:存储两个整数,并按照各位数字的逆序存放,实现两个整数的加法
以p、q为头节点的两个链表,用tempP,tempQ记录两个链表上的节点
以result作为r的链表的头节点,用r记录结果链表上的节点
- 若p,q均不为0: p+q+carry
- p或者q结束后: p=q;r=p+carry;
- p和q都结束了:r=carry ( 即可能存在进位)
void add(LNode *p,LNode *q,LNode *&result){
LNode *tempP=p->next; LNode *tempQ=q->next;
result=(LNode *)malloc(sizeof(LNode));
result->next=NULL;
LNode *r=NULL;
r=result;
int carry=0;
while(tempP!=NULL&&tempQ!=NULL){
LNode *temp=(LNode *)malloc(sizeof(LNode)); temp->next=NULL;
temp->data=(tempP->data+tempQ->data+carry)%10; carray= (tempP->data+tempQ->data+carry)/10;
r->next=temp; r=r->next;
tempP=tempP->next; tempQ=tempQ->next;
}
if(tempP==NULL) tempP=tempQ;
while(tempP!=NULL){
LNode *temp=(LNode *)malloc(sizeof(LNode));
temp->next=NULL;
temp->data=(tempP+carry)%10;
carry=(tempP+carry)/10;
r->next=temp; r=r->next;
tempP=tempP->next;
}
if(carry>0){
LNode *temp=(LNode *)malloc(LNode);
temp->next=NULL;
temp->data=carry;
r->next=temp;
}
}
时间复杂度max(m,n)
空间复杂度max(m,n)
队列
链表栈只能顺序存储,而顺序栈不但能顺序存储,还能直接存储(x)
栈要求只能在表的一端访问、插入、删除,所以栈只能顺序访问,不能直接存取
二叉树
概念辨析
平衡二叉树是指左右子树的高度差的绝对值不大于1的二叉树(x)
平衡二叉树是排序二叉树
线索二叉树是物理结构(正确)
后序线索树的遍历仍需要栈的支持(正确)
二叉树与度为2的有序树
二叉树
- 度为0,1,2
- 可为空
- 绝对有序
度为2的有序树
4. 度为0,1,2
5. 至少三个节点
6. 相对有序
二叉树的链式存储
typedef struct node{
ElemType data;
struct node *lchild;
struct node *rchild;
}BTNode;
求双亲
二叉树的二叉链表方式存储,求p所指节点的双亲节点
- 树为空,return null
- 树只有p,return null
- 递归结束点:树的左子或右子是p,return t
- 递归getParent(t->lchild,p);
BTNode *getParent(BTNode *t,BTNode *p){
if(t==NULL) return NULL;
if(t==p) return NULL;
if(t->lchild==p||t->rchild==p)return t;
BTNode *parent=getParent(t->lchild,p);
if(parent) return parent;
else return getParent(t->rchild,p);
}
时间复杂度o(n)
孩子-兄弟链表存储结构
由给定的二元组(f,c),f表示双亲,c表示孩子,构建孩子兄弟链表存储结构
层次遍历
void level(BTNode *b)
{
BTNode *p; BTNode *qu[MAXSIZE];
int front,rear; front=rear=0;
rear++; qu[rear]=b;
while(front!=rear){
front=(front+1)%MAXSIZE; p=qu[front]; printf("%d",p->data);
if(p->lchild){ rear=(rear+1)%MAXSIZE; qu[rear]=p->lchild; }
if(p->rchild){ rear=(rear+1)%MAXSIZE; qu[rear]=p->rchild; }
}
}
递增有序的二叉排序树(前序递增有序)转化为递减有序的二叉树
typedef struct BTNode{
char data;
struct BTNode *lchild;
struct BTNode *rchild;
}BTNode;
void reverseLR(BTNode *root){
if(root){
reverse(root->lchild);
reverse(root->rchild);
}
BTNode *temp=root->lchild;
root->lchild=root->rchild;
root->rchild=temp;
}
高度
typedef struct node{struct node *lchild;struct ndoe *rchild;int data;}BTNode;
//高度
void level(BTNode *b){
BTNode *qu[MAXSIZE];
int front,rear,last,level;
front=rear=-1;
level=last=0;
BTNode *p;
qu[++rear]=b;
while(rear!=front){
p=qu[++front];
if(p->lchild){ qu[++rear]=p->lchild; }
if(p->rchild){ qu[++rear]=p->rchild; }
if(last==front){ level++;last=rear;}
}
return level;
}
从下之上,从右向左的层次遍历
//从下之上,从右向左的层次遍历
void level(BTNode *b){
BTNode *qu[MAXSIZE];
BTNode *st[MAXSIZE];
int top=-1;
int front,rear,last,level;
front=rear=-1;
level=last=0;
BTNode *p;
qu[++rear]=b;
while(rear!=front){
p=qu[++front];
st[++top]=p;
if(p->lchild){ qu[++rear]=p->lchild; }
if(p->rchild){ qu[++rear]=p->rchild; }
if(last==front){ level++;last=rear;}
}
while(top>-1){p=st[top--];printf("%d",p->data);}
}
宽度==最大的层节点总数
//宽度==最大的层节点总数
typedef struct{BTNode data[MAXSIZE];int level[MAXSIZE];int front,rear;}Qu;
void level(BTNode *b){
BTNode *p;
Qu.front=Qu.rear=-1;
Qu.data[++Qu.rear]=b;Qu.level[++Qu.rear]=1;
while(Qu.rear!=Qu.front){
p=qu[++Qu.front];k=Qu.level[Qu.front]
if(p->lchild){ Qu.data[++Qu.rear]=p->lchild; Qu.level[Qu.rear]=k+1;}
if(p->rchild){ Qu.data[++Qu.rear]=p->rchild; Qu.level[Qu.rear]=k+1;}
}
int max=0,k=1;
int i=0;
while(i<=Qu.rear){
n=0;
while(i<=Qu.rear&&Qu.level[i]==k){n++;i++;}
k=Qu.level[i];
if(n>max) max=n;
}
return max;
}
后序遍历
typedef struct node{
int data;
struct node *lchild;
struct node *rchild;
}BTNode;
void Post(BTNode *b){
if(b){
Post(b->lchild);
Post(b->rchild);
printf("%d",b->data);
}
}
void post(BTNode *b){
BTNode *st[MAXSIZE];
BTNode *p,*r;
p=b;
int top=flag=-1;
while(p||top>-1){
if(p){st[++top]=b;p=p->lchild;}//p节点存在,就访问所有左子树
else{//p不存在,取栈顶元素
p=st[top];
if(p->rchild&&p->rchild!=r)p=p->rchild;//p右子树存在且未被访问 ,转向右
else{p=st[top--]; printf("%d",p->data);r=p; p=NULL;}//右子树不存在或者访问过了,弹出节点并访问,记录刚访问过的节点
}
}
}
图
图的遍历
//邻接矩阵
typedef struct{int no;char info;}vextype;
typedef struct{int edge[MAXV][MAXV];int n,e;vextype vex[MAXV];}MGraph;
//邻接表
typedef struct ANode{int adjvex;struct ANode *next;int weight;}ANode;
typedef struct VNode{ANode *first;int data;}VNode;
typedef ANode AdjList[MAXV];
typedef struct{AdjList adjlist;int n,e;}AGraph;
//DFS
int visited[MAXV]={0};
void DFS(AGraph *g,int v){
ANode *p;
p=g.adjlist[v].first;
printf("%d,",v);
visited[v]=1;
while(p){
if(!visited[p.adjvex]) DFS(g,p.adjvex);
p=p.next;
}
}
//BFS
void BFS(AGraph *g,int v)
{
ANode *p;
int visited[MAXV];int w;
int qu[MAXV]; int front,rear;
visited[v]=1; printf("%d",v);
rear=(rear+1)%MAXV; qu[rear]=v;
while(front!=rear){
front=(front+1)%MAXV; w=qu[front];
p=g.adjlist[w].first;
while(p){
if(!visited[p.adjvex]){
rear=(rear+1)%MAXV; qu[rear]=p.adjvex;
visited[p.adjvex]=1; printf("%d",p.adjvex);
}
p=p->next;
}
}
}
有向无环图是否存在一个顶点,到其余顶点都有一条有向路径,g以邻接表存储
typedef struct ArcNode{int adjvex;struct ArcNode *next;}ArcNode;
typedef struct{int data;ArcNode *first}VNode;
typedef struct{VNode adjList[MAXSIZE];int n,e;}AGraph;
void DFS(AGraph *g,int v,int visitedp[],int &n){
int visited[g.n]={0};
visited[v]=1;
ArcNode *p;
++n;
p=g.adjList[i].first;
while(p){
if(!visited[p->adjvex]) DFS(g,p->adjvex,visited,n);
p=p->next;
}
}
bool isOneToAll(AGraph *g){
int visited[maxsize];
for(int i=0;i<g.n;++i){
for(int j=0;j<g.n;j++)visited[j]=0;
int N=0;
DFS(g,i,visited,N);
if(N==g.n)return true;
}
return false;
}
AOE
所有的关键活动提前完成,那么整个工程将会提前完成(正确)
关键路径是最长路径(正确)
Dijkstra算法
算法:
- dist初始化为v到i的距离,s设所有i都为0
- path初始化,若v-i有路径,就设为path[i]=v,若v-i没有路径,就设为-1
- s[v]=1,即将开始的节点v放入集合s
- 循环n-1次:
- 每次选择不在s集合中的点中,选择除dist中最短的路径(u=min(dist[j])),并将最短路径上的u点纳入s集合中
- 刚纳入的u点,如果能过缩短dist ,就修改dist
//dij求v到其余顶点的最短路径
void Dijkstra(MGraph g,int v){
int dist[MAXV];int path[MAXV];int s[MAXV];
int mindis;
for(int i=0;i<g.n;i++){
dist[i]=g.edge[v][i];
s[i]=0;//表示i点在u中,不在s中
if(g.edge[v][i]<INF) path[i]=v;
else path[i]=-1;
s[v]=1;
for(int i=0;i<g.n-1;i++){
mindis=INF;
for(int j=0;j<g.n;j++){
if(s[j]==0&&dist[j]<mindis) {u=j;mindis=dist[j];}
}
printf("%d",u);
s[u]=1;
for(int j=0;j<g.n;j++){
if(s[j]==0){
if(g.e[u][j]<INF&&dist[u]+g.edge[u][j]<dist[j]){
dist[j]=dist[u]+g.edge[u][j];
path[j]=u;
}
}
}
}
}
DispAllPath(g,dist,path,s,v);
}
带权有向图的单目标最短路径,即求各个顶点到顶点v的最短路径
算法:单源最短路径算法中图的边全部反向,可得到单目标最短路径,也就是其余顶点到某一顶点的最短路径
void Dijkstra(int n,float MGraph[][n],int v0,int dist[],int path[])
{
int set[MAXSIZE];
int min,v;
for(int i=0;i<n;++i){
dist[i]=MGraph[i][v0];
set[i]=0;
if(MGraph[i][v0]<INF) path[i]=v0;
else path[i]=-1;
}
set[v0]=1;path[v0]=-1;
for(int i=0;i<g.n-1;++i){
min=INF;
for(int j=0;j<n;j++){
if(set[j]==0&&dist[j]<min){
v=j;min=dist[j];
}
}
}
set[v]=1;
for(int j=0;j<n;++j){
if(set[j]==0&&dist[v]+MGraph[j][v]<dist[j]){
dist[j]=dist[v]+MGraph[j][v];
path[j]=v;
}
}
}
floyd算法
有向无环图g以邻接矩阵存储,求最长路径长度
将g边值改为负值,如此求出floyd最短路径长度的绝对值就是g的最长路径长度
拓扑排序
typedef struct Anode{struct *Anode next;int adjvex;int weight}Anode;
typedef struct Vnode{Anode *first;int data;int count;}Vnode;//count入度
typedef Vnode AdjList[MAXV];
typedef struct{AdjList adjlist;int n,e;}AGraph;
int TopSort(AGraph *g,int topsq[]){
int st[MAXV];
int top=-1;
int i,j,n=0;
Anode *p;
for(i=0;i<g.n;i++){
if(g.adjlist[i].count==0)st[++top]=i;
while(top>-1){
i=st[top--];
topsq[n]=i;n++;
p=g.adjlist[i].first;
while(p){
j=p->adjvex;
g.adjlist[j].count--;
if(!g.adjlist[j])st[++top]=j;
p=p->next;
}
}
}
if(n<g.n) return 0;
else return 1;
}
有向无环图用邻接表存储,不用栈和队列实现拓扑排序
算法:用数组记录各个顶点的入度,根据输入的顶点和数组中其他顶点的来修改其余各个顶点的度,从数组中找出一个入度为0的顶点输出,如此循环,直到所有顶点都被输出为止。
void topsort(AGraph *g){
int visited[MAXSIZE];
int in[MAXSIZE];
ANode *r;
//初始化
for(int i=0;i<g.n;i++){ visited[i]=0; in[i]=0;}
//计算入度
for(int i=0;i<g.n;i++){
r=g.adjlist[i].first;
while(r!=NULL){
++in[r->adjvex];r=r->next;
}
}
for(int i=0;i<g.n;j++){
for(int j=0;j<g.n;j++){
//找出度为0的点
if(in[j]==0&&visited[j]==0)break;
if(j==g.n)return false;
//输出度为0,并且改变其他的点的入度
visited[j]=1;
printf("%d",g.adjlist[j].data);
ANode *r=g.adjlist[j].first;
while(r){
--in[r->adjvex];r=r->next;
}
}
}
}