数据结构编程题

本文涵盖了多种数据结构和算法的应用,包括链表、二叉树、图的遍历和操作,如循环队列的入队和出队、二叉树的层次遍历、图的广度优先和深度优先搜索、堆排序、冒泡排序、二分查找等。此外,还涉及了邻接矩阵和邻接表在图处理中的应用,以及链表中元素的交换和查找算法。
摘要由CSDN通过智能技术生成


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;//将标记位置为1

    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);//出队
                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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值