1.采用一个不带头结点只有一个尾结点指针rear的循环单链表存储队列,设计队列的初始化、进队和出队等算法。
void initQueue(LinkList *&rear)//初始化队列
{
rear=null;
}
bool queueEmpty(LinkList *rear)//判断队空的算法
{
return rear==null;
}
void enQueue(LinkList *&rear,ElemType x)//进队算法
{
LinkList *p;
p=(LinkList*)malloc(sizeof(LinkList ));//创建新结点
p->data=x;
if(rear==null)//原队列为空
{
p->next=p;//构成循环队列
rear=p;
}
else
{
p->next=rear->next;//将P节点插入到rear之后
rear->next=p;
rear=p;//rear指向新插入的节点
}
}
bool deQueue(LinkList *&rear,ElemType &x)//出队算法
{
LinkList*q;
if(rear==null)
{
return fasle;//队空
}
else if(rear->next=next)//原队列只有一个节点
{
x=rear->data;
free(rear);
}
else
{
q=rear->next;
x=q->data;
rear->next=q->next;
free(q);
}
return true;
}
2.用链表设计一个直接插入排序的算法
void insertsort(LinkList *L)
{
LinkList p,q,pre;
p=L->next->next;//指向第二个元素
L->next->next=null;
while(p)
{
q=p->next;//保存后继节点
pre=L;//从头开始遍历
while(pre->next!=null&&pre->next->data<p->data)
{
pre=pre->next;
}
p->next=pre->next;
pre->next=p;
p=q;
}
}
3.用链表设计一个简单选择的排序算法
void selectsort(linklist L)
{
linklist p,q;
p=q=L->next;
int temp;
while(q)
{
p=min(p)//返回值最小的节点
temp=p->data;//这三行代码是交换值
p->data=q->data;
q->data=p->data;
q=q->next;
p=q;
}
}
linklist min(linklist p)//寻找链表值最小的节点
{
int data=p->data;
linklist temp=p;
p=p->next;
while(p){
if(data>p->data)
{
temp=p;
data=p->data
}
p=p->next;
}
return temp;
}
4.将一个邻接矩阵转化为邻接表
#include <stdio.h>
#include <malloc.h>
//#include "graph.h"
#include<iostream>
using namespace std;
typedef int InfoType;
#define MAXV 100 //最大顶点个数
#define INF 32767 //INF表示∞
//以下定义邻接矩阵类型
typedef struct
{ int no; //顶点编号
InfoType info; //顶点其他信息
} VertexType; //顶点类型
typedef struct //图的定义
{ int edges[MAXV][MAXV]; //邻接矩阵
int n,e; //顶点数,边数
VertexType vexs[MAXV]; //存放顶点信息
} MGraph; //图的邻接矩阵类型
//以下定义邻接表类型
typedef struct ANode //边的节点结构类型
{ int adjvex; //该边的终点位置
struct ANode *nextarc; //指向下一条边的指针
InfoType info; //该边的相关信息,这里用于存放权值
} ArcNode;
typedef int Vertex;
typedef struct Vnode //邻接表头节点的类型
{ Vertex data; //顶点信息
ArcNode *firstarc; //指向第一条边
} VNode;
typedef VNode AdjList[MAXV]; //AdjList是邻接表类型
typedef struct
{ AdjList adjlist; //邻接表
int n,e; //图中顶点数n和边数e
} ALGraph; //图的邻接表类型
void MatToList(MGraph g,ALGraph *&G)
//将邻接矩阵g转换成邻接表G
{ int i,j;
ArcNode *p;
G=(ALGraph *)malloc(sizeof(ALGraph));
for (i=0;i<g.n;i++) //给邻接表中所有头节点的指针域置初值
G->adjlist[i].firstarc=NULL;
for (i=0;i<g.n;i++) //检查邻接矩阵中每个元素
for (j=g.n-1;j>=0;j--)
if (g.edges[i][j]!=0) //存在一条边
{ p=(ArcNode *)malloc(sizeof(ArcNode)); //创建一个节点*p
p->adjvex=j;
p->nextarc=G->adjlist[i].firstarc; //采用头插法插入*p
G->adjlist[i].firstarc=p;
/********************************/
//因为是无向图,所以它的邻接矩阵应该是对称的
p=(ArcNode *)malloc(sizeof(ArcNode)); //创建一个节点*p
p->adjvex=i;
p->nextarc=G->adjlist[j].firstarc; //采用头插法插入*p
G->adjlist[j].firstarc=p;
}
G->n=g.n;G->e=g.e;
}
void ListToMat(ALGraph *G,MGraph &g)
//将邻接表G转换成邻接矩阵g
{ int i;
ArcNode *p;
for (i=0;i<G->n;i++)
{ p=G->adjlist[i].firstarc;
while (p!=NULL)
{ g.edges[i][p->adjvex]=1;
p=p->nextarc;
}
}
g.n=G->n;g.e=G->e;
}
void DispMat(MGraph g)
//输出邻接矩阵g
{
int i,j;
for (i=0;i<g.n;i++)
{
for (j=0;j<g.n;j++)
printf("%3d",g.edges[i][j]);
printf("\n");
}
}
void DispAdj(ALGraph *G)
//输出邻接表G
{
int i;
ArcNode *p;
for (i=0;i<G->n;i++)
{
p=G->adjlist[i].firstarc;
printf("%3d: ",i);
while (p!=NULL)
{
printf("%3d",p->adjvex);
p=p->nextarc;
}
printf("\n");
}
}
//以下主函数用作调试
int main()
{
int i,j;
MGraph g,g1;
ALGraph *G;
int m,n;
cin>>n>>m;
int A[n][n];
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>A[i][j];
}
}
g.n=n;g.e=m;
for (i=0;i<g.n;i++)//将矩阵转化为邻接矩阵
for (j=0;j<g.n;j++)
g.edges[i][j]=A[i][j];
5.用栈实现十进制与二进制的转化
#define N 100
typedef int ElemType
typedef struct{
ElemType data[M];
in top;
}
//初始化栈
13 void InitStack(Stack *s)
14 {
15 s->top = -1;
16 }
//进栈
17 int Push(Stack *s,ElemType e)
18 {
19 if (s->top == M-1)
20 {
21 printf("栈满\n");
22 return 0;
23 }
24 s->top++;
25 s->data[s->top]=e;
26 return 1;
27 }
28
29 //判断栈是否为空
30 int Empty(Stack *s)
31 {
32 return(s->top==-1);
33 }
34 //出栈
35 int Pop(Stack *s,ElemType *e)
36 {
37 if(Empty(s))
38 {
39 printf("\n Stack is free");
40 return 0;
41 }
42 *e=s->data[s->top];
43 s->top--;
44 return 1;
45 }
46
47 void Conversion(int N)
48 {
49 int e;
50 Stack *s = (Stack *)malloc(sizeof(Stack));
51 InitStack(s);
52 while(N)//十进制转成二进制
53 {
54 Push(s,N%2);//将余数进栈
55 N=N/2;//模/2
56 }
57 while(!Empty(s))
58 {
59 Pop(s,&e);//出栈
60 printf("%d",e);
61 }
62 }
6.设计一个求结点x在二叉树中的双亲结点算法
typedef struct node
{
int data;
struct node *lchild,*rchild;
} bitree;
bitree *q[20];
int r=0,f=0,flag=0;
void preorder(bitree *bt, char x)
{
if (bt!=0 && flag==0)
{
if (bt->data==x)
{
flag=1;
return;
}else{
r=(r+1)%20;
q[r]=bt;
preorder(bt->lchild,x);
preorder(bt->rchild,x);
}
}
}
void parent(bitree *bt,char x)
{
int i;
preorder(bt,x);
for(i=f+1; i<=r; i++)
if (q[i]->lchild->data==x || q[i]->rchild->data==x)
break;
if (flag==0)
printf("not found x\n");
else if (i<=r)
printf("%c",q[i]->data);
else
printf("not parent");
}
7.只设一个头,一个元素的计数器,不设尾指针,循环队列
//入队算法
void enQueue(int x)
{
int temp;
if(count==n)//元素达到数组上限
{
printf("队列上溢了!");
}
else
{
count++;//元素个数加1
temp=(count+front)%n;//求尾指针
Queue[temp]=x;//元素入队
}
}
//出队算法
int deQueue()
{
int temp;
if(count==0)
{
printf("队列下溢");
}
else
{
temp=Queue[front];//取出元素
front=(front+1)%n;//取出头指针
count--;//元素个数减一
return temp;
}
}
8.二叉树交换左右孩子子树
struct BiTree{
char data;
BiTree *lchild,*rchild;
}//二叉树的结构体//下面是通过递归排序实现的。先序遍历实现的代码
void ExChange(BiTree *T)
{
BiTree *temp=new BiTree();
if(T->lchild!=null&&T->rchild!=null)//左右孩子都不为空,进行交换
{
temp=T->rchild;
T->rchild=T->lchild;
T->lchild=temp;
}
}
else
{
return ;
}
if(T->lchild!=null)//左子树不为空,继续向下进行寻找
{
ExChange(T->lchild);
}
if(T->rchild!=null)//右子树不为空,也继续向下进行寻找
{
ExChange(T->rchild);
}
}
void ExChange_preorder(BiTree t)//递归前序遍历,打印结点值
{
if(t)
{
printf("%c",t->data);
ExChange_preorder(t->lchild);
ExChange_preorder(t->rchild);
}
}
9.用栈模拟一个字符串是不是回文字符串
typedef int ElemType;
typedef struct{
int top;//栈顶指针
ElemType data[Maxsize];
}SqStack;//定义顺序栈
void InitStack(SqStack *&s)//初始化栈
{
s=(SqStack*)malloc(sizeof(SqStack));
s->top=-1;
}
void DestroyStack(SqStack *&s)//销毁栈
{
free(s);
}
bool StackEmpty(SqStack *s)//判空
{
return s->top==-1;
}
bool push(SqStack *&s,ElemType e)//进栈
{
if(s->top==Maxsize-1)//栈满
{
return false;
}
s->data[s->top++]=e;
return true;
}
bool Push(SqStack *&s,ElemType e)//出栈
{
if(s->top==Maxsize-1)//进栈判满
return false;
e=s->data[s->top--];
return true;
}
bool symmetry(String str)//判断一个字符串是不是对称串
{
ElemType e;
SqStack *st;
InitStack(st);//初始化栈
for(int i=0;i<str.length();i++)//元素进栈
{
Push(st,str[i]);
}
for(int i=0;i<str.length();i++)
{
Pop(str,e);//出栈,e存放的就是当前栈顶元素
if(e!=str[i])//元素不同
{
DestroyStack(st);//销毁栈
return false;
}
}
DestroyStack(st);//
return true;
}
10.堆排序的算法如下,最好适应于筛选前k个最大的元素
//堆排序筛选或调整算法
void shift(int R[],int low,int high)
{
int i=low,j=2*i;
int temp=R[i];
while(j<high)
{
if(j<high&&R[j].key<R[j+1].key)//j指向大孩子
j++;
if(temp.key<R[j].key)//双亲小,向下继续进行筛选
{
R[i]=R[j];
i=j;
j=2*i;
}
else
break;//双亲大,不再调整
}
R[i]=temp;
}
void HeapSort(int R[],int n)
{
int i,temp;
for(i=n/2;i>=1;i--)//循环建立初始堆
shift(R,i,n);
for(i=n;i>=2;i--)//进行n-1次循环 ,完成堆排序
{
temp=R[1];
R[1]=R[i];
R[i]=temp;//将第一个结点和最后一个结点交换位置
shift(R,1,i-1);//筛选R[1]结点,得到i-1个结点的堆
}
}
11.图的深度遍历,采用邻接表的DFS算法。
void DFS(AdjList *G,int v)
{
ArcNode *p;
int w;
visited[v]=1;//置已访问标记
printf("%d ",v);//输出被访问的顶点编号
p=G->adjlist[v].firstarc//p指向顶点V的第一条边的 边头节点
while(p!=NULL)
{
w=p->adjvex;//顶点编号
if(visited[w]==0)
DFS(G,W);//若w顶点未访问,递归访问它
p=p->nextarc;//p指向顶点V的下一条边头节点
}
}
深度优先遍历距离初始顶点越远越先访问它。
12.图的广度遍历,采用邻接表的BFS算法
void BFS(AdjGraph *G,int v)
{ int w,i;
ArcNode *p;
SqQueue *qu; //定义环形队列指针
InitQueue(qu); //初始化队列
int visited[MAXV]; //定义顶点访问标记数组
for(i=0;i<G->n;i++)
visited[i]=0; //访问标记数组初始化
printf("%2d",v); //输出被访问顶点的编号
visited[v]=1; //置已访问标记
enQueue(qu,v);
}while(QueueEmpty(qu)) //队不空循环
{
deQueue(qu,w); //出队一个顶点w
p=G->adjlist[w].firstarc; //指向w的第一个邻接点
while(p!=NULL) //查找w的所有邻接点
{
if (visited[p->adjvex]==0) //若当前邻接点未被访问
{
printf("%2d",p->adjvex); //访问该邻接点
visited[p->adjvex]=1; //置已访问标记
enQueue(qu,p->adjvex); //该顶点进队
}
p=p->nextarc; //找下一个邻接点
}
}
printf("\n");
}
//距离初始顶点越近越优先访问,通过队列来实现
13.假设图G采用邻接表存储,设计一个算法,判断无向图G是否连通。若连通则返回true;否则返回false。
int visited[Maxsize];
bool Connect(AdjGraph *G)
{
int i;
bool flag=true;
for(i=0;i<G->n;i++)
visited[i]=0;
DFS(G,0)//调用DFS算法,从顶点0开始进行深度优先遍历
for(i=0;i<G->n;i++)
{
if(visited[i]==0)//如果有一个顶点未访问到,返回false.
{
flag=false;
break;
}
}
return flag;
}
14.返回图G中编号为V的顶点的出度
int OutDegree(ALGraph *G,int v)
{
ArcNode *p;
int n=0;
p=G->adjlist[v].firstarc//p指向顶点V的第一条边的
while(p!=NULL)
{
n++;
p=p->nextarc;
}
return n;
//求出度为0的顶点个数
if(p==NULL)//如果头指针为空,则该顶点的出度为0.
{
printf("%d",i);
}
}
15.用数组实现图的深度优先遍历
int visited[n];
graph g[][100];
int n;
dfs(int k)
{
int j;
print("visited",k);
visited[k]=1;//将标记位置为1
for(int j=1;j<=n;j++)
{
if(g[k][j]==1&&visited[j]==0)//如果顶点j为被访问过,则顶点j是新出发点
{
dfs(j);//递归
}
}
}
16.图的广度优先遍历,通过数组存储来实现的
void BFSTraverse(MGraph *G)
{
int i, j;
Queue Q;for (i=0; i<G->numVertexes; ++i)
visited[i] = FALSE;//将标记位置为1InitQueue(&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);//出队
for (j=0; j<G->numVertexes; ++j)
{
if (!visited[j]&&G->arc[i][j]!=INFINITY)
{
visited[j] = TRUE;
printf("%c ", G->vexs[j]);//打印元素
EnQueue(&Q, j);//元素入队列
}
}
}
}
}
}
图的存储结构有两种,一种是数组,另外一种是邻接表只是两种的判断情况有稍微的区别
17.二叉树的层次遍历
层次遍历使用到了广度优先搜索,技巧:深度优先用递归,广度优先用队列二叉树的层次遍历
void LevelOrder(BtNode *ptr)
{
if(ptr==NULL)
{
return ;
}
queue<BtNode*>que;
que.push(ptr);
while(!que.empty())
{
ptr=que.front();
que.pop();
cout<<ptr->data<<" ";
if(ptr->lchild!=NULL)
{
que.push(ptr->lchild);
}
if(ptr->rchild!=NULL)
{
que.push(ptr->rchild);
}
}
}
18.计算树中结点的个数
public int nubmerOfNodes(BinaryNode<T> root)
{
int nodes=0;
if(root==null)
{
return 0;
}
else
{
node=1+nubmerOfNodes(root.lchild)+nubmerOfNodes(root.rchild);
}
return node;
}
19.将元素的所有奇数移到偶数前面
通过快速排序来实现
void move(char num[])
{
int i=0,j=num.length;
int temp;
while(i<j)
{
while(j>=0&&num[j]%2==0)//从最后一个元素找,如果是偶数就不用动
{
j--;
}
while(i<j&&num[i]%2==1)//从最前一个元素开始找,如果是奇数就不用动
{
i++;
}
if(i<j) //交换两个元素的值
{
t=num[j];
num[j]=num[i];
num[i]=t;
}
}
}
20.将链表的最小元素值移到最前面,不能申请新的的空间值
找到尾结点之前,需要删除这个结点,必须先找到这个结点的前驱节点,找到这个结点之后,通过头插法来实现
void move(LinkList head)
{
LinkList pre=head->next,p=pre->next;
Linklist min=pre,pre_min;
if(pre==NULL)
{
printf("这个链表是空值");
}
while(p)
{
if(min->data>p->data)
{
pre_min=pre;//用来更新最小值的前驱
min=p;
}
pre=p;//用来保存最小值的前驱
p=p->next;
}
}
pre_min=min->next;//删除这个链表
min->next=head->next;//移到链表的最前端
head->next=min;//头插法来实现
return 1;
}
21.设计在二叉排序树上查找结点x的算法,找到了返回指针x,否则返回NULL
节点首先和根节点的值进行比较,比根节点的值小,则从左孩子进行比较,大的话就从右孩子进行比较。
bitree *bstsearch(bitree *t,int key)
{
bitree *p=t;
while(p!=NULL)
{
if(p->data==key)
{
return p;
}
else if(p->key<key)
{
p=p->rchild;
}
else
{
p=p->lchild;
}
}
return NULL;
}
22.简单的冒泡排序算法
public static int[]BubbleSort(int []data)
{
int size=data.length;
int temp;
for(int i=0;i<size-1;i++)
for(int j=0;j<size-1-i;j++)//将最大的值放在最后面
{
if(data[j]>data[j+1])//交换两个元素的位置
{
temp=data[j];
data[j]=data[j+1];
data[j+1]=temp;
}
}
return data;
}
23.改进版的双向冒泡排序,交替的正反两个方向来进行
双向冒泡排序只是局部进行优化,整体的时间复杂度并没有任何变化。
void BidBUbbleSort(int array[],int n)
{
int low=0,high=n-1;
while(low<high)
{
for(int i=low;i<high;i++)//从前往后找
{
if(array[i]>array[i+1])
{
Swap(&array[i],&array[i+1]);
}
}
high--;//找到一个最大值,放在末尾
for(int i=high;i>low;i--)//反向冒泡,从后往前找
{
if(array[i]<array[i-1])
{
Swap(&array[i],&array[i-1]);
}
}
low++;//找到一个最小值,就放到后面
}
}
24.二叉树统计叶子节点和非叶子节点个数的算法
typedef struct BiTree{ //结构体的定义
int data;
struct BiTree *rchild,*lchild;
}
int leafCount(BiTree T)
{
int count;
if(T==NULL)
{
count=0;
}
else if(T->rchild==NULL&&T->lchild==NULL)
{
count=1;
}
else
{
count=leafCount(T->lchild)+leafCount(T->rchild);
}
return count;
}
//统计非叶子结点的个数
int leafCount(BiTree T)
{
int count;
if(T==NULL)
{
return 0;
}
if(T->rchild!=NULL&&T->lchild!=NULL) //前序遍历
{
count++;
}
leafCount(T->rchild);
leafCount(T->lchild);
return count;
}
25.统计有向图中每个顶点的出度和入度,假如有向图采用邻接矩阵进行存储。
/*首先先写结构体*/
#define INFINITY 65535
#define MAX_VERTEX_NUM 100
typedef char VertexType;
typedef struct {
VertexType vexs[MAX_VERTEX_NUM]; //顶点数组
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
int v, e; //图顶点和边的数量
} MGraph;
void CreatMGraph(MGraph &G)//首先创建图
{
int i,j,k,w;
printf("输入顶点数和边数");
scanf("%d%d",&G.v,&G.e);
for(i=0;i<G.v;i++)
{
for(j=0;j<G.v;j++)
{
G.arc[i][j]=INFINITY//初始化邻接矩阵
}
}
for(k=0;k<G.e;k++)
{
printf("输入边(i,j)上的坐标i,j和权w\n");
scanf("%d%d%d",&i,&j,&w);
G.arcs[i][j]=w;
}
}
void Input(MGraph G)//计算每个顶点的入度
{
int sum=0,n=0;
for(int i=0;i<G.v;i++)
{
for(int j=0;j<G.v;j++)
{
if(G.arcs[j][i]!=INFINITY)//将数组反过来进行遍历
{
n++;
}
}
printf("%d",n)
n=0;
}
}void Output(MGraph G)//计算每个顶点的出度
{
int n=0;
printf("出度为:\n");
for(int i=0;i<G.v;i++)
{
for(int j=0;j<G.v;j++)
{
if(G.arcs[i][j]!=INFINITY)
{
n++;
}
}
if(n==0)//计算出度为0的节点
num++;
printf("%d",n);
n=0;
}
}
26.统计有向图中每个顶点的出度和入度,假设采用邻接表进行存储。
//先写结构体
#define INFINITY 65535
#define MAX_VERTEX_NUM 100
typedef int VertexType;
int num=0;
typedef struct ArcNode {
int adjvex; //邻接顶点的标号
int weight; //权重
ArcNode *nextarc;
} ArcNode; //边表
typedef struct {
VertexType data; //VertexType可以写成结构体类型存储信息
ArcNode *firstarc;
} VNode; //顶点数组
typedef struct {
VNode adjlist[MAX_VERTEX_NUM];
int v, e;
} ALGraph;
void CreatMGraph(ALGraph &G)//创建邻接表
{
int i,j,k;
ArcNode *e;
printf("输入顶点数和边数:\n");
scanf("%d%d",&G.v,&G,e);
for(i=0;i<G.v;i++)
{
G.adjlist[i].firstarc=NULL;//首先将头指针置为空
}
for(k=0;k<G.e;k++)
{
printf("输入边(vi,vj)上的顶点序号:\n");
scanf("%d%d",&i,&j);
e=(ArcNode*)malloc(sizeof(ArcNode));
e->adjvex=j;
e->nextarc=G.adjlist[i].firstarc;//采用头插法
G.adjlist[i].firstarc=e;
}
}
void indu(ALGraph G)//采用邻接表存储,计算每个节点的入度
{
int i,j,n=0;
int A[G.v];
for(i=0;i<G.v;i++)
A[i]=0;
ArcNode *e;
for(j=0;j<G.v;j++)
{
while(G.adjlist[j].firstarc!=NULL)
{
A[G.adjlist[j].firstarc->adjvex]++;//通过一个数组来计算节点出现的个数
//就相当于删除这个节点
e=G.adjlist[j].firstarc->nextarc;
G.adjlist[j].firstarc=e;
}
}
for(i=0;i<G.v;i++)
{
printf("%d",A[i]);
}
}
void outdu(ALGraph G)//计算每个节点的出度
{
int n=0,i=0;
ArcNode *e;
for(i=0;i<G.v;i++)
{
while(G.adjlist[i].firstarc!=NULL)
{
n++;
e=G.adjlist[i].firstarc->nextarc;//相当于删除边节点
G.adjlist[i].firstarc=e;
}
if(n==0)
{
num++;
}
printf("%d ",n);
n=0;
}
}
27.二分查找的代码
public static int Method(int []num,int low,int high,int target)//时间复杂度比顺序查找要小
{
int low=0,high=num.length,middle;
while(low<=high)
{
middle=(low+high)/2;
if(target==num[middle])
{
return middle;
}
else if(target>num[middle])
{
low=middle+1;
}
else
high=middle-1
}
return -1;
}
28.试用二叉链表存储二叉树,实现二叉树的先序遍历、中序遍历、后序遍历的递归算法
typedef struct TreeNode //定义结构体
{
int data;
TreeNode *left;
TreeNode *right;
}
void pre_order(TreeNode *Node)//前序遍历递归算法
{
if(Node==NULL)
{
printf("%d ",Node->data);//输出数据域
}
pre_order(Node->left);
pre_order(Node->right);
}void middle_order(TreeNode *Node)//中序遍历递归算法
{
if(Node!=NULL)
{
middle_order(Node->left);
printf("%d ",Node->data);
middle_order(Node->right);
}
}void post_order(TreeNode *Node)//后序遍历的递归算法
{
if(Node!=NULL)
{
post_order(Node->left);
post_order(Node->right);
printf("%d ",Node->data);
}
}
29.计算二叉树的高度
typedef struct BiTree//定义结构体
{
int data;
BiTree *lchild;
BiTree *rchild;
}
public int getHeight(BiTree root)
{
if(root==NULL)
{
return 0;
}
int left_height=getHeight(root->lchild);//左孩子高度
int right_height=getHeight(root->rchild);//右孩子高度
return (left_height>right_height?left_height:right_height)+1;//返回最大的高度
}
30.用层次遍历求二叉树的高度
因为层次遍历是将每一层元素都输出后才遍历下一层,所以我们可以在遍历完每一层的最后一个结点后高度加一。如何判断是否为当前层的最后一个结点呢?可以用queue.size()来判断,当size(当前层元素个数),当size=0时即遍历完该层元素。
代码:
int maxDepth(TreeNode *root)//层次遍历求高度
{
if(root==NULL)
{
return 0;
}
queue<TreeNode*>Q;
Q.push(root);
int height=0;
int len=0;
while(!Q.empty())
{
int size=Q.size();//记录的是同一层的节点个数
len=Math.max(len,size);//记录的是最大宽度
while(size--)
{
TreeNode *temp=Q.front();
Q.pop();
if(temp->left!=NULL)
{
Q.push(temp->left);
}
if(temp->right!=NULL)
{
Q.push(temp->right);
}
}
height++;
}
return height;
}
31.将两个有序的单链表合并成一个单链表并保持有序的算法
public ListNode Merge(ListNode list1,ListNode list2)
{
if(list1==NULL)
{
return list2;
}
if(list2==NULL)
{
return list1;
}
ListNode newhead;
newhead->next=NULL;
while(list1!=NULL&&list2!=NULL)
{
if(list1.data<list2.data)
{
newhead.next=list1;
newhead=list1;
list1=list1.next;
}
else if(list2.data<list1.data)
{
newhead.next=list2;
newhead=list2;
list2=list2.next;
}
else //相同的元素则同时进行移动
{
newhead.next=list2;
newhead=list2;
list1=list1.next;
list2=list2.next;
}
}
while(list1!=NULL)//链表1未遍历到末尾
{
newhead.next=list1;
newhead=list1;
list1=list1.next;
}
while(list2!=NULL)//链表2未遍历到末尾
{
newhead.next=list2;
newhead=list2;
list2=list2.next;
}
newhead.next=NULL;
}
32.用单链表去实现 一个LRU算法
1:如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的结点,并将其从原来的位置删除,然后再插入到链表的头部。
2:如果此数据没有在缓存链表中,又可以分为两种情况:
如果此时缓存未满,则将此结点直接插入到链表的头部;
如果此时缓存已满,则链表尾结点删除,将新的数据结点插入链表的头部。
private final static Integer DEFAULT_CAPACITY=10;
private NOde<T> headNode;//头节点
private Integer length;//长度
private Integer capacity;
public LRUBaseLinkedList()
{
this.headNode=new NOde<>();
this.length=0;
this.capacity=DEFAULT_CAPACITY;
}
public LRUBaseLinkedList(Integer capacity)
{
this.headNode=new Node<>();
this.length=0;
this.capacity=capacity;
}
public void lru(T data)
{
Node preNode=findPerNode(data);
if(perNode!=NULL)
{
deleteElement(perNode);
insertElementHead(data);
}
else
{
if(length>=this.capacity)
{
deleteElementEnd();
}
insertElementHead(data);
}
}
//删除表中最后一个元素
private void deleteElementEnd()
{
Node p=headNode;
if(p.next==null)
return ;
while(p.next.next!=NULL)//删除节点的前驱节点
{
p=p.next;
}
Node end=p.next;
p.next=null;
end=null;
length--;
}
//在链表头部插入元素
private void insertElementHead(T data)
{
Node p=headNode.next;
Node newNode=new Node(data,p);
headNode.next=newNode;
length++;
}
//删除前驱的下一个节点
private void deleteElement(Node preNode)
{
if(perNode!=NULL)
{
Node temp=perNode.next;
perNode.next=temp.next;
temp.next=NULL;
length--
}
}
//获取元素的前一个结点
private Node findPerNode(T data)
{
NOde p=headNode;
while(p.next!=NULL)
{
if(p.next.element==data)
{
return p;
}
p=p.next;
}
}
return NULL;
}
//打印结点值
private void printAll()
{
Node node=headNode.next;
while(node!=NULL)
{
soutnode.element+" ");
node=node.next;
}
}
定义结点
public class Node<T>
{
T element;
NOde next;
public Node()
{
}
int a[N];
public NOde(T element,Node next)
{
thi.element=element;
this.next=next;
}
public T getElement()
{
return element;
}
public void setElement(T element)
{
this.element=element;
}
public Node getNext()
{
return next;
}
public void setNext(Node next)
{
this.next=next;
}
}
33.线性表元素递增且按顺序存储在数组中
//1:用最少的时间在表中查找值为x的元素
//2:若找到则将其于直接后继元素交换
//3: 若找不到则将其插入表中,使表中元素仍然递增有序
typedef struct SeqenceList
{
ElemType data[Maxsize];
int length;
}SqList;
int find_x_2(SqList &L,int x)//二分查找
{
int left=0,right=l.length-1,mid;
while(left<=right)
{
mid=(left+right)/2;
if(L.data[i]==x)//找到这个元素
{
break;
}
else if(L.data[mid]<x)
{
left=mid+1;
}
else
{
right=mid-1;
}
}
if(L.data[mid]==x&&mid!=L.length-1)//找到了这个元素,将这个元素和它的后继换一个位置
{
int temp;
temp=L.data[mid];
L.data[mid]=L.data[mid+1];
L.data[mid+1]=temp;
}
if(left>right)//如果没有找到,将这个元素插入到这个数组中
{
int len=L.length;
for(int i=len-1;i>mid;i--)
{
L.data[i+1]=L.data[i];
}
L.data[mid+1]=x;
L.length++;
}
return 0;
}
//
int find(int a[],int x)
{
int len=a.len-1;
for(int i=0;i<=len;i++)
{
if(a[i]==x)
{
return i;
}
}
return -1;
int a[0]==x;
for(i<=a.length; ;i--)
{
if(a[i]==x)
{
return i;
}
}
}
34.进行链表的反转
ListNode *reverse(ListNode *head)
{
ListNode *temp;
ListNode *cur=head,*pre=NULL;
while(cur)
{
temp=cur->next;//保存后继节点
cur->next=pre;//进行翻转操作
pre=cur;
cur=temp;
}
}
35.两两交换链表中的两个元素,不是只交换两个数据的值,而是整个节点。
ListNode *swapPairs(ListNode *head)
{
ListNode *dummyHead=new ListNode(0);//设置一个虚拟头节点
dummyHead->next=head;
ListNode *cur=dummyHead;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
ListNode *tmp=cur->next;//记录临时节点
ListNode *tmp1=cur->next->next;//记录第二个节点的后继节点
cur->next=cur->next->next;
cur->next->next=tmp;
cur->next->next->next=tmp1;
cur=cur->next->next;//移动两位,准备下一轮的交换
}
return dummyHead->next;
}
//删除链表中的倒数第k个节点
ListNode *RemoveNode(ListNode *head,int n)
{
ListNode *dummyHead=new ListNode(0);
dummyHead->next=head;
ListNode *slow=dummyHead;
ListNode *fast=dummyHead;
while(n--&&fast!=NULL)
{
fast=fast->next;
}
fast=fast->next;//fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while(fast!=NULL)
{
fast=fast->next;
slow=slow->next;
}
slow->next=slow->next->next;
return dummyHead->next;
}
36.有效的字母异位词
通过数组来实现,数组本质上也是一个哈希表
bool isAngram(String s,String t)
{
int record[26]={0};
for(int i=0;i<s.length();i++)
{
record[s[i]-'a']++;//字母的ASCII码是连续的
}
for(int i=0;i<t.length();i++)
{
record[t[i]-'a']--;
}
for(int i=0;i<26;i++)
{
if(record[i]!=0)//不相同的元素
{
return fasle;
}
}
return true;
}
37.求两个数组中的共同元素
int []intersection(int nums1[],int nums2[])
{
if(nums1==null||nums1.length==0||nums2==null||nums2.length==0)
{
return new int[0];
}
Set<Integer>set1=new HashSet<>();
Set<Integer>resSet=new HashSet<>();
for(int i:nums1)//遍历数组1
{
set1.add(i);
}
for(int i:nums2)
{
if(set1.contains(i))
{
resSet.add(i);
}
}
int []resArr=new int[resSet.size()];
int index=0;
//将结果转化为数组
for(int i:resSet)
{
resArr[index++]=i;
}
return resArr;
}
//判断一个数字是不是是快乐数
boolean isHappy(int n)
{
Set<Integer>record=new HashSet<>();
while(n!=1&&!record.contains(n))
{
record.add(n);
n=getNextNumber(n);
}
return n==1;
}
private int getNextNumber(int n)
{
int res=0;
while(n)
{
res+=n%10*n%10;
n/=10;
}
return res;
}
//求两数之和
public int[] twoSum(int nums[],int target)
{
int []res=new int[2];
if(nums==null||nums.length==0)
{
return res;
}
Map<Integer,Integer>map=new HashMap<>();
for(int i=0;i<nums.length;i++)
{
int temp=target-nums[i];
if(map.containsKey(temp))
{
res[1]=i;
res[0]=map.get(temp);
}
map.put(nums[i],i);
}
return res;
}
//进行括号匹配
bool isValid(String s)
{
stack<int>st;
for(int i=0;i<s.size();i++)
{
if(s[i]=='(')
st.push(')');
else if(s[i]=='{')
st.push('}');
else if(s[i]=='[')
st.push(']');
else if(st.empty()||st.top()!=s[i])
return fasle;
else
st.pop();
}
return st.empty();
}
//删除字符串中的所有相邻重复项
string removeDuplicate(string S)
{
stack<char>st;
for(char s:S)
{
if(st.empty()||s!=st.top())
{
st.push(s)
}
else
{
st.pop();//元素相同就出栈
}
}
String result="";
while(!st.empty())//将栈中元素放到result字符串汇总
{
result+=st.top();
st.pop();
}
reverse(result.begin(),result.end());//此时将字符串反转一下
return result;
}
//翻转二叉树
TreeNode *invertTree(TreeNode* root)
{
if(root==NULL)
{
return root;
}
swap(root->left,root->right);
invertTree(root->left);
invertTree(root->right);
}
//通过深度优先遍历来实现
TreeNode* invertTree(TreeNode* root)
{
if(root==NULL)return root;
stack<TreeNode*>st;
st.push(root);
while(!st.empty())
{
TreeNode* node=st.top();//中
st.pop();
swap(node->left,node->right);
if(node->right) st.push(node->right);//左
if(node->left) st.push(node->left);//右
}
return root;
}
//通过二叉树的层次遍历来翻转这棵树
TreeNode* invertTree(TreeNode* root)
{
queue<TreeNode*>que;
if(root!=NULL) que.push(root);
while(!que.empty())
{
int size=que.size();
for(int i=0;i<size;i++)
{
TreeNode* node=que.front();
que.pop();
swap(node->left,node->right);
if(node->left)
que.push(node->left);
if(node->right)
que.push(node->right);
}
}
return root;
}
判断二叉树是否是对称二叉树
compare(TreeNode* left,TreeNode* right)
{
if(left==NULL&&right==NULL)
{
return false;
}
else if(left!=NULL&&right==NULL)
return false;
else if(left->val!=right->val)
return false;
else
return compare(left->left,right->right)&&compare(right->left,left->right);
}
通过层次遍历求二叉树的最大深度
int maxdepth(treenode* root) {
if (root == null) return 0;
int depth = 0;
queue<treenode*> que;
que.push(root);
while(!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
treenode* node=que.front();
que.pop();
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return depth;//返回的是 最大深度
}
};
求n叉树的的最大深度
int maxdepth(node* root){
queue<node*> que;
if (root != null) que.push(root);
int depth = 0;
while (!que.empty()) {
int size = que.size();
depth++; // 记录深度
for (int i = 0; i < size; i++) {
node* node = que.front();
que.pop();
for (int j = 0; j < node->children.size(); j++) {
if (node->children[j]) que.push(node->children[j]);//多个孩子节点入栈
}
}
}
return depth;
}
二叉树的最小深度
int minDepth(TreeNode* root)
{
if(root==NULL) return 0;
int depth=0;
queue<TreeNode*>que;
que.push(root);
while(!que.empty())
{
int size=que.size();
depth++;
for(int i=0;i<size;i++)
{
TreeNOde *node=que.front();
que.pop();
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
if(!node->left&&!node->right)//节点从上到下,从左到右遍历,第一个遍历到叶子节点的是最低高度
return depth;
}
}
return depth;
}
求二叉树的左子节点个数
int sumOfLeftLeaves(TreeNode* root)
{
if(root==NULL)
{
return 0;
}
int leftValue=sumOfLeftLeaves(root->left);
int rightValue=sumOfLeftLeaves(root->right);
int midValue=0;
if(root->left&&!root->left->left&&!root->left->right)
{
midValue=root->left->val;
}
int sum=midValue+leftValue+rightValue;
return sum;
}
删除有序链表中的重复元素
ListNode* deleteDuolication(ListNode* pHead)
{
if(pHead==nullptr) return nullptr;
ListNode* node=(ListNode*)malloc(sizeof(ListNode));
node=pHead;
while(node)
{
if(node->next!=nullptr&&node->val==node->next->val)
{
while(node->next!=nullptr&&node->val==node->next->val)//先要判断node->next不为空,然后在进行判断,否则容易空指针异常
{
node->next=node->next->next;
}
}
node=node->next;
}
return pHead;
}