题型
编程题2题,综合题5题

编程题

链表的遍历,对单链表进行基本操作。

数组实现

//a.线性表储存结构
#include<iostream>
using namespace std;
#define maxlength 100
struct LIST{
   
     Elementtype elements[maxlength];
     int last;};
typedef int position;
//b.插入
void Insert(Elementtype x,position p,LIST &L)
{
   position q;
 if(L.last>maxlength-1)
cout<<"list is full!"<<endl;
 else if((p>L.last+1)||(p<1))
cout<<"position does not exist!"<<endl;
 else{
   
 for(q=L.last;q>=p;q--)
{
      elements[q+1]=L.elements[q];
last=L.last+1;
elements[p]=x;}}}
//c.删除
void Delete(position p,LIST &L)
{
   position q;
 if((p>L.last)||(p<1))
   cout<<"position does not exist!"<<endl;
 else{
   L.last=L.last-1;
      for(q=p;q<=L.last;q++)
L.elementss[q]=L.elements[q+1];}}
//d.定位
position Locate(Elementtype x,LIST L)
{
   position q;
 for(q=1;q<=L.last;q++)
 {
   if(L.elements[q]==x)
return q;
  return(L.last+1);}}


指针实现

#include<iostream>
using namespace std;
//a. 储存结构
struct celltype{
   
     Elementtype element;
     celltype *next;};
typedef celltype *LIST
typedef celltype *position

//b. 插入
void Insert(Elementtype x,position p)

{
   position temp;
 temp=p->next;
P->next=new celltype;
P->next->element=x;
P->next->next=temp;}

//c.删除
void Delete(position p)
{
   position q;
 if(p->next!=NULL){
   
q=p->next;
p->next=q->next;
delete q;}}

//d.定位
postion Locate(Elementtype x,LIST L)
{
   postion p;
 p=L;
 while(p->next!=NULL)
if(p->next->element==x)
   return p;
else p=p->next;
 return p;}

//e.置空
postion MakeNull(LIST &L)
{
   L=new celltype;
L->next=NULL;
return L;} 

二叉树的遍历,判断两个二叉树是否等价。

遍历

//先根遍历DLR
void PreOrder(BTREE BT)
{
   if(!IsEmpty(BT))
 {
   visit(Data(BT));
  PreOrder(Lchild(BT));
  PreOrder(Rchild(BT));}}

//中根遍历LDR
void InOrder(BTREE BT)
{
   if(!IsEmpty(BT))
 {
   InOrder(Lchild(BT));
  visit(Data(BT));
  InOrder(Rchild(BT));}}

//后根遍历LRD
void PostOrder(BTREE BT)
{
   if(!IsEmpty(BT))
 {
   PostOrder(Lchild(BT));
  PostOrder(Rchild(BT));
  visit(Data(BT));}}

//中根遍历非递归函数
void NInOrder(BTREE BT)
{
   STACK S;BTREE T;
 MakeNull(S);
 T=BT;
 while(!IsEmpty(T)||!Empty(S))
if(!IsEmpty(T))
{
   Push(T,S);
 T=Lchild(T);}
else
{
   T=Top(S);Pop(S);
 visit(Data(T));
 T=Rchild(T);}}

//层次遍历(队列)
void LeverOrder(BTREE BT)
{
   Queue Q;BTREE T;
 MakeNull(Q);
 T=BT;
 if(!IsEmpty(T))
EnQueue(T,Q);
 while(!Empty(Q))
 {
   T=Front(Q);
  visit(Data(T));
  DeQueue(T);
  if(!Lchild(T))
     EnQueue(Lchild(T),Q);
  if(!Rchild(T))
     EnQueue(Rchild(T),Q);}}

判断两二叉树是否等价

boolean Equal(BTREE firstbt,BTREE secondbt)
{
   boolean x;
 x=FALSE;
 if(IsEmpty(firstbt)&&IsEmpty(secondbt))
x=TRUE;
 else if(!IsEmpty(firstbt)&&!IsEmpty(secondbt))
if(Data(firstbt)==Data(secondbt))
   if(Equal(Lchild(firstbt),Lchild(secondbt)))
      x=Equal(Rchild(firstbt),Rchild(secondbt));
 return x;}
#include<iostream>
#include <stack>
using namespace std;
struct BTREE {
   
	int data;
	BTREE* lchild;
	BTREE* rchild;
};
BTREE* Lchild(BTREE* BT) {
   
	return BT->lchild;
}
BTREE* Rchild(BTREE* BT) {
   
	return BT->rchild;
}
int Data(BTREE* BT) {
   
	return BT->data;
}
bool IsEmpty(BTREE* BT) {
   
	return BT == NULL;
}
void PreOrder(BTREE* BT) {
   //前序遍历
	if (!IsEmpty(BT)) {
   
		//visit(Data(BT));
		PreOrder(Lchild(BT));
		PreOrder(Rchild(BT));
	}
}
void InOrder(BTREE* BT) {
   //中序遍历
	if (!IsEmpty(BT)) {
   
		InOrder(Lchild(BT));
		//visit(Data(BT));
		InOrder(Rchild(BT));
	}
}
void PostOrder(BTREE* BT) {
   //后序遍历
	if (!IsEmpty(BT)) {
   
		PostOrder(Lchild(BT));
		PostOrder(Rchild(BT));
		//visit(Data(BT));
	}
}
void NINORDER(BTREE* BT) {
   
	stack<BTREE*> S;
	while (!S.empty() || BT != NULL) {
   
		if (BT != NULL) {
   
			S.push(BT);
			BT = BT->lchild;
		}
		else {
   
			BT = S.top();
			S.pop();
			//visit(DATA(BT));
			BT = BT->rchild;
		}
	}
}
bool equal(BTREE* BT1, BTREE* BT2) {
   
	bool x = false;
	if (BT1 == NULL && BT2 == NULL)
		x = true;
	else if (BT1 != NULL && BT2 != NULL) {
   
		if (Data(BT1) == Data(BT2))
			if (equal(Lchild(BT1), Lchild(BT2)))
				x = equal(Rchild(BT1), Rchild(BT2));
	}
	return x;
}
int main() {
   

}

哈夫曼树的构造原理以及构造过程,带权路径长度

//数据结构
#define n 100 //叶子树
#define m 2*(n)-1 //结点总数
typedef struct{
   
double weight;
int lchild;
int rchild;
int parent;}HTNODE;
typedef HTNODE HuffmanT[m];

//构造
void SelectMin(HuffmanT T,int n,int &p1,int &p2)
{
   int i,j;
 for(i=0;i<n;i++)
if(T[i].parent==-1)  {
   p1=i;break;}
 for(j=i+1;j<n;j++)
if(T[j].parent==-1)  {
   p2=j;break;}
 for(i=o;i<n;i++)
if((T[p1].weight>T[i].weight)&&(T[i].parent==-1)&&(p2!=i)) p1=i;
 for(j=0;j<n;j++)
    if((T[p2].weight>T[j].weight)&&(T[j].parent==-1)&&(p1!=j)) p2=j;}
void CreateHT(HuffmanT T)
{
   int i,p1,p2;
 InitHT(T);
 for(i=n;i<=m;i++)
 {
   SelectMin(T,i-1,p1,p2);
  T[p1].parent=T[p2].parent=i;
  T[i].lchild=p1;
  T[i].rchild=p2;
  T[i].weight=T[p1].weight+T[p2.weight];}

#define n 100//叶子数
#define m 2*n-1//节点总数
struct HTNODE
{
   
	double weight;
	int lchild;
	int rchild;
	int parent;
};
typedef HTNODE HuffmanT[m + 1];
void CreateHT(HuffmanT T,int w[],int num) {
   
	int i, p1, p2;
	for (i = 1; i < 2 * num; i++) {
   
		T[i].parent = -1;
		T[i].lchild = -1;
		T[i].rchild = -1;
	}
	for (int i = 1; i <= num; i++) {
   
		T[i].weight = w[i];
	}
	for (int i = num + 1; i <= 2 * num - 1; i++) {
   
		SelectMIN(T, i - 1, p1, p2);
		T[p1].parent = T[p2].parent = i;
		T[i].weight = T[p1].weight + T[p2].weight;
		T[i].lchild = p1;
		T[i].rchild = p2;
	}
}
void SelectMIN(HuffmanT T, int position, int& p1, int& p2) {
   
	int i, j;
	for (i = 1; i <= position; i++) {
   
		if (T[i].parent == -1) {
   
			p1 = i;
			break;
		}
	}
	for (j = i + 1; j <= position; j++) {
   
		if (T[j].parent == -1) {
   
			p2 = j;
			break;
		}
	}
	for (i = 1; i <= position; i++) {
   
		if ((T[p1].weight > T[i].weight) && (T[i].parent == -1) && (i != p2))
			p1 = i;
	}
	for (j = i + 1; j <= position; j++) {
   
		if ((T[p2].weight > T[j].weight) && (T[j].parent == -1) && (j != p1))
			p2 = j;
	}
}
int main() {
   

}

计算图中顶点间最短路径(单源最短路径以及任意顶点之间的最短路径)和最短距离的基本思想。如何计算图的偏心度和中心点。

单源最短路径

void Dijkstra(C)
{
   S={
   1};
 for(i=2;i<=n;i++)
D[i]=C[1][i];
 for(i=1;i<=n-1;i++)
 {
   从V-S中选出一个w,使D[w]的值最小;
  把w加入S;
  for(V-S中的每个顶点v)
     D[v]=min(D[v],D[w]+C[w][v])} //时间复杂度O(n²)

每一对顶点之间的最短路径

//Floyd算法
void Floyd(A,C,n)
{
   for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
   A[i][j]=C[i][j];
 for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
   for(j=1;j<=n;j++)
      if(A[i][k]+A[k][j]<A[i][j])
         A[i][j]=A[i][k]+A[k][j];}

//Warshall算法
void Warshall(A,C,n)
{
   for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
   A[i][j]=C[i][j];
 for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
   for(j=1;j<=n;j++)
      A[i][j]=A[i][j](A[i][k]∩A[k][j]);}

计算图的偏心度和中心点

偏心度E(k)=max{d[i][k]|i∈V},d[i][j]表示从i到j的最短距离。
求有向图的中心点:
①使用Floyd算法,求每对顶点最短路径的矩阵D.
②对矩阵D的每列j求最大值:E(j)=max{d[i][j]}. //顶点j的偏心度
③求出具有最小偏心度的顶点k:E(k)=min{E(j)}. //即为图G的中心点

综合题

给定树的两种遍历序列,如何确定树

堆的定义以及相关的基本操作

堆的定义

堆即是一棵完全二叉树

//最大堆的类型定义:
#define MaxSize 200
typedef struct{
   
int key;}
Elementtype;
typedef struct{
   
Elementtype elements[MaxSize];
int n;}HEAP;

创建空堆

void MaxHeap(HEAP heap)
{
   heap.n=0;}

判断堆是否为空

bool HeapEmpty(HEAP heap)
{
   return(!Heap.n);}

判断堆是否为满

bool HeapFull(HEAP heap)
{
   return(heap.n==Maxsize-1);}

最大堆heap中插入新元素item

void Insert(HEAP heap,Elementtype item)
{
   int i;
 if(!HeapFull(heap))
 {
   i=heap.n+1;
while((i!=1)&&(item>heap.elements[i/2]))
{
   heap.elements[i]=heap.elements[i/2];
 i/=2;}}
 heap.elements[i]=item;}

最大堆删除最大元素

Elementtype DeleteMax(HEAP heap)
{
   int parent=1,child=2;
 Elementtype item,tmp;
 if(!HeapEmpty(heap))
 {
   item=heap.elements[1];
  tmp=heap.elements[heap.n--];
  while(child<=heap.n)
  {
   if((child<heap.n)&&(heap.elements[child]<heap.elements[child+1]))
      child++;
   if(tmp>=heap.elements[child])  break;
   heap.elements[parent]=heap.elements[child];
   parent=child;
   child*=2;}
  heap.elements[parent]=tmp;
  return item;}}
#include<iostream>
#define MAXSIZE 100
using namespace std;
struct HEAP {
   
	int elements[MAXSIZE];
	int n;
};
void MaxHeap(HEAP& heap) {
   
	heap.n = 0;
}
bool HeapFulls(HEAP& heap) {
   
	return heap.n == MAXSIZE - 1;
}
bool HeapEmpty(HEAP& heap) {
   
	return heap.n == 0;
}
void Insert(HEAP& heap, int element) {
   
	if (!HeapFulls(heap)) {
   
		int i = ++heap.n;
		while (i != 1 && element > heap.elements[i / 2]) {
   
			heap.elements[i] = heap.elements[i / 2];
			i /= 2;
		}
		heap.elements[i] = element;
	}
}
void DeleteMax(HEAP& heap) {
   
	if (!HeapEmpty(heap)) {
   
		int parent = 1, child = 2;
		int temp = heap.elements[heap.n--];
		while (child <= heap.n) {
   
			if (heap.elements[child] < heap.elements[child + 1])
				child++;
			if (temp >= heap.elements[child])break;
			heap.elements[parent] = heap.elements[child];
			parent = child;
			child *= 2;
		}
		heap.elements[parent] = temp;
	}
}
int main() {
   

}

KMP算法中如何计算模式串中的next数组,以及KMP模式匹配的具体步骤

next数组的计算

第1位:0.
第2位:1.
第n位(n>=3):比较前n-1位,得出最长前后缀匹配长度k,填k+1.

void GetNext(char *t,int next[])
{
   int i=0,j=0;
 next[1]=0;
 while(i<t[0])
 {
   if(j==0||t[i]==t[j])
  {
   i++;j++;next[i]=j;}
  else j=next[j];}}

KMP模式匹配具体步骤

若第k-1次比较在j=m处失配,那第k次比较j回溯到j=next[m]处同主串的i比较(主串不回溯),具体可参照p65例2-11

最小生成树(两种方法)的基本原理以及生成过程

最小生成树

生成树是连接V中所有顶点的一棵开放树,生成树中所有边长的总和称为生成树的价,使这个价最小的生成树称为图G的最小生成树

Prim算法

void Prim(costtype C[n+1][n+1])
{
   costtype LOWCOST[n+1];
 int CLOSEST[n+1]int i,j,k;
 costtype min;
 for(i=2;i<=n;i++)
 {
   LOWCOST[i]=C[1][i];
  CLOSEST[i]=1;}
 for(i=2;i<=n;i++)
 {
   min=LOWCOST[i];
  k=i;
  for(j=2;j<=n;j++)
      if(LOWCOST[j]<min)
      {
   min=LOWCOST[i];
       k=j;}
  cout<<(<<k<<,<<CLOSEST[k]<<)<<endl;
 LOWCOST[k]=infinity;
 for(j=2;j<=n;j++)
     if(C[k][j]<LOWCOST[j]&&LOWCOST[j]!=infinity)
     {
   LOWCOST[j]=C[k][j];
      CLOSEST[j]=k;}}}  //O(n²),一般用于顶点不太多的情况

Kruskal算法

void Kruskal(EdgeSet edges,int n,int e)
{
   int bnf,edf;
 MFSET parents;
 Sort(Edges);
 for(int i=1;i<=n;i++)
     Initial(i,parents);
 for(i=1;i<=e;i++)
 {
   bnf=Find(edges[i].begin,parents);
  edf=Find(edges[i].end,parents);
  if(bnf!=edf)
  {
   Union(bnf,edf,parents);
   cout<<ˋ(ˊ<<edges[i].begin<<ˋ,ˊ;
   cout<<edges[i].end<<ˋ,ˊ<<edges[i].cost<<ˋ)ˊ;
   cout<<endl;}}  //O(|E|*log2|E|),适合于求边稀疏的最小生成树

图的关键路径的基本原理以及生成过程

关键路径

AOE网:V(事件)–E(活动)–W(时间)
AOV网:V(活动)–E(先后关系)
关键路径:起始点–结束点的最大长度路径
事件最早发生时间:v1到vi的最长路径
活动最早开始时间(=事件最早发生时间):E(i)
活动最迟开始时间:L(i)
关键活动:满足E(i)=L(i)
活动可延缓时间=L(i)-E(i)

二叉查找树的定义以及相关基本操作

定义

struct celltype{
   
records data
celltype *lchild,rchild;};
typedef celltype *BST;

基本操作

//a. F所指二叉查找树中查找关键字为K的记录(F为二查找树根节点的指针)
BST Search(keytype k,BSTF)
{
   if(F=NULL)
   return NULL;
 else if(k==F->data.key)
   return F;
 else if(k<F->data.key)
   return(Search(k,F->lchild));
 else(k>F->data.key)
   return(Search(k,F->rchild));}

//b. 插入记录R
Void Insert(records R,BST *F)
{
   if(F==NULL)
 {
   F=new celltype;
F->data=R;
F->lchild=NULL;
F->rchild=NULL;}
 else if(R.key<F->data.key)
   Insert(R,F->lchild);
 else if(R.key>F->data.key)
   Insert(R,F->rchild);}

//c.删除继承结点
Records DeleteMin(BST &F)
{
   records tmp;BST P;
 if(F->lchild==NULL)
 {
   P=F;
  tmp=F->data;
  F=F->rchild;
  delete P;
  return tmp;}
 else return(DeleteMin(F->lchild));}

//d.删除关键字为k的结点
Void delete(keytype k,BST &F)
{
   if(F!=NULL)
   If(k<F->data.key)
     Delete(k,lchild);
   Else if(k>F->data.key)
     Delete(k,rchild);
   Else/*k==F->data.key,删除成功*/
   If(F->rchild==NULL)
     F=F->rchild;
   If(F->lchild==NULL)
     F=F->lchild;
   Else
     F->data=DeleteMin(F->rchild);}

构造AVL树的基本方法,掌握四种平衡处理(旋转)的基本原理,并能够判断何时需要旋转、需要进行哪一种旋转以及如何旋转

类型

int unbanlanced=FALSE;
struct node{
   
records data;
int bf;
node *lchild,rchild;};
typedef node *BST;

LL旋转和LR旋转

void LeftRotation(BST &T,int &unbalanced)
{
   BST gc,lc;
 lc=T->lchild;
 if(lc->bf==1)     //LL旋转
 {
   T->lchild=lc->rchild;
  lc->rchild=T;
T->bf=0;
T=lc;}
 else{
                //LR旋转 
  gc=lc->rchild;
  lc->rchild=gc->lchild;
  gc->lchild=lc;
T->lchild=gc->rchild;
gc->rchild=T;
switch(gc->bf)
{
   case 1:T->bf=-1;
        lc->bf=0;
        break;
 case 0:T->bf=lc->bf=0;
        break;
 case -1:T->bf=0;
         lc->bf=1;}
T=gc;}
T->bf=0;
unbanlanced=FALSE;}

插入新纪录

void AVLInsert(BST &T,records R,int &unbalanced)
{
   if(!T)
 {
   /*向空二叉树插入元素*/
  T=new celltype;
T->data=R;
T->lchild=T->rchild=NULL;
T->bf=0;}
 else if(R.key<T->data.key)
 {
   AVLInsert(T->lchild,R,unbalanced);
  if(unbalanced)
     switch(T->bf)
     {
   case -1:T->bf=0;
              unbalanced=FALSE;
              break;
      case 0:T->bf=1;
             break;
      case 1:LeftRotation(T,unbalanced);}}
 else if(R.key>T->data.key)
 {
   AVLInsert(T->rchild,R,unbalanced);
  if(unbalanced)
     switch(T->bf)
     {
   case -1:T->bf=0;
              unbalanced=FALSE;
              break;
      case 0:T->bf=-1;
             break;
      case 1:RightRotation(T,unbalanced);}}
 else/*查找成功,R已在AVL中*/
   unbalanced=FALSE;}