数据结构考试重点(个人复习用)

尚未完成,全部内容,当做一个知识点梳理还算可以
排序:

直接插入排序:
思想:每次选择一个数,从一组数的第二个数开始一直到最后一个,每次从选择的这个数开始向前,如果遍历到的数大于目前我选择的数,那么令遍历到的数向后移动一位。
复杂度:平均 n2 正序:n 逆序:n2
稳定性:稳定
代码:

void insertsort(int a[],int n)
    {
        int j,temp,i;
        for(i=1;i<n;i++)
        {
            temp=a[i];
            for(j=i-1;j>=0&&temp<a[j];j--)
                a[j+1]=a[j];
            a[j+1]=temp;
        }
    }

希尔排序(跳跃式插入排序)
思想:在直接插入排序的基础上利用二进制拆分对区间进行拆分。
复杂度: 平均 n*log2n 正序:n1.3 最坏情况:n2
稳定性:不稳定

void mysort::shellsort(int a[],int n)
{
    int j,d,i,temp;
    for(d=n/2;d>=1;d/=2)
    {
        for(i=d;i<n;i++)
        {
          temp=a[i];
          for(j=i-d;j>=0&&a[j]>temp;j-=d)
                a[j+d]=a[j];
          a[j+d]=temp;
        }
    }
}

冒泡排序
思想:每一次必然能放置一个最大值到最后位置,那么第一次范围就是1-n,然后n不断减1,每一次遍历都要对比所有范围内的数据,并且把范围内的最大值放到最末尾,有点像选择排序
改进:我们不妨设置一个变量e,存储每一次遍历后最大值放到哪里了,比如第三次遍历就放到了n-5的位置那么显然就能避免两次遍历
稳定性:稳定

复杂度:平均 :n2 正序:n 逆序:n2

void mysort::Bubblesort(int a[],int n)
{
    int j,e,bound,temp;
    e=n-1;
    while(e)
    {
        bound=e;
        e=0;
        for(j=0;j<bound;j++)
        {
            if(a[j]>a[j+1])
            {
                temp=a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
                e=j;
            }
        }
    }
}

选择排序
思想:每次选一个最小的放到最前面,范围从1到n不断缩小至n-1到n
复杂度: 对初始序列并不敏感 遍历复杂度均为:n2 但是注意,初始序列仍会对交换这一操作产生影响。
稳定性:稳定

void selectsort(int a[],int n)
    {
       int pos=0;
       for(int i=0;i<n;i++)
       {
           pos=i;
           for(int j=i+1;j<n;j++)
           {
               if(a[pos]>a[i])
               {
                   pos=j;
               }
           }
           if(pos!=i)
           {
               swap(a[pos],a[i]);
           }
       }
    }

堆排序
思想:建立根堆
根堆:就是完全二叉树,初始堆是层序建立的,后调整为大根堆或小根堆
调整:从最后一个不为叶子的节点开始,保证左右子节点权值均小于(大根堆)或大于(小根堆)根节点。
动图表示:

复杂度:对初始序列并不敏感 nlog2n
稳定性:不稳定
代码:

void mysort::heapsort(int n,int a[])
{
    int i,temp;
    for(i=ceil(n/2)-1;i>=0;i--)
    {
        modify(i,a,n-1);
    }
    for(i=1;i<n;i++)
    {
        temp=a[0];
        a[0]=a[n-i];
        a[n-i]=temp;
        modify(0,a,n-i-1);
    }
}
void mysort::modify(int k,int a[],int last)
{
    int i,j,temp;
    i=k,j=2*i+1;
    while(j<=last)
    {
        if(j<last&&a[j]<a[j+1])j++;
        if(a[i]>a[j])break;
        else
        {
            temp=a[i];a[i]=a[j];a[j]=temp;
            i=j;
            j=2*i+1;
        }
    }
}

快速排序(轴值排序)
思想:每次选定第一个数为轴值(通常是这样的),调整轴值位置到左方均小于轴值和右方均大于轴值

复杂度: 平均:nlog2n 最好:nlog2n 正序或者逆序: n2
代码

int mysort::partition1(int f,int l,int a[])
{
    int i=f;
    int j=l;
    int temp;
    while(i<j)
    {
        while(i<j&&a[i]<=a[j])j--;
        if(i<j)
        {
            temp=a[i];
            a[i]=a[j];
            a[j]=temp;
            i++;
        }
        while(i<j&&a[i]<=a[j])i++;
        if(i<j)
        {
           temp=a[i];
           a[i]=a[j];
           a[j]=temp;
           j--;
        }
    }
    return i;
}
void mysort::quicksort(int a[],int first,int last)
{
     if(first>=last)
     {
         return;
     }
     else
     {
         int p=partition1(first,last,a);
         quicksort(a,first,p-1);
         quicksort(a,p+1,last);
     }
}

不难看出,我们最优秀的快速排序实际上是基于划分的递归.

二路归并排序(二路分治排序)
这个考程序的概率低,暂且不搞代码了
思想:分治
复杂度: 对初始序列不敏感 n*log2n

基数排序

查找

考点:查找长度(成功,失败),二叉排序数(建立),二叉平衡树(调整,LL,RR,LR,RL)B数基本概念(阶数与分支),哈希(基本概念,建立-冲突-堆积)

平衡二叉树
1.第一步确定类型
找到引起不平衡节点,找到最小不平衡子树,从最小不平衡子树的树根向引发点走两步
2.旋转
RR LL型旋转一次,LR,RL型旋转两次(第一次在最小不平衡子树的下一个节点上做一次普通旋转,然后再在原本最小不平衡子树上做一次普通旋转)
旋转,以此节点为待旋转点,旋转方向所有子树层次下降1,待旋转点和非旋转方向子树上升1;

图论
极有可能设计到的编程:BFS DFS遍历图
其他考点:Prim(按点寻最小生成),Kruskal(按边寻最小生成),Dijkstra(暴力最短路径),Floyd(背包DP寻找最短路径),AOV网和拓扑排序AOE网和关键路径,这些考点在考研和期末考试掌握思想,了解程序即可。
邻接矩阵存储:
BFS:

///图的存储:邻接矩阵存储,vis数组为标记数组,vertexnum为节点树,edge[][]记录了点之间的边信息
void BFS(int n)///从n开始BFS遍历,
{
    bool vis[vertexnum]=false;
    int q[vertexnum];
    int rear=first=-1,temp;
    q[++rear]=n;
    while(rear!=first)
    {
        temp=q[++first];
        cout<<temp<<endl;
        vis[temp]=true;
        for(int i=0;i<vertexnum;i++)
        {
            if(!vis[i]&&edge[i][j])
            {
                q[++rear]=i;
            }
        }
    }
}

DFS:

bool vis[vertexnum];
void DFS(int n)///从n开始BFS遍历,
{
   vis[n]=true;
   cout<<n<<endl;
   for(int i=0;i<vertexnum;i++)
   {
      if(!vis[i]&&edge[n][i])
      {
          DFS(i);
      }
   }
}

链表存储(小概率,但是很重要,也很可能会考)
BFS
重点:这个需要理解链表图的结构

struct vertex
{
   int vertex;
   edge *first;  
}adjlist[vertexnum];
struct edge 
{
   int vertex;
   edge *next;
};
bool vis[vertexnum];
void BFS(int n)///从n开始BFS遍历,
{
    bool vis[vertexnum]=false;
    int q[vertexnum];
    int rear=first=-1;
    int temp;
    q[++rear]=n;
    while(rear!=first)
    {
        temp=q[++first];
        cout<<temp<<endl;
        vis[temp]=true;
        edge *p=nullptr;
        p=adjlist[temp].first;
        while(p!=nullptr)
        {
            if(!vis[p->vertex])
                q[++rear]=p->vertex;
            p=p->next;
        }
    }
        
}

DFS

void DFS(int n)
{
    cout<<n<<endl;
    vis[n]=true;
    edge *p=nullptr;
    p=adjlist[n].first;
    while(p!=nullptr)
    {
        if(!vis[p->vertex])
            DFS(p->vertex);
        p=p->next;
    }
}

拓扑排序与AOV网
高大上的名字看上去感觉好像是什么高深的东西,实际上就是个 等级排序和时间顺序表。
解释一下:比如我们要做一锅汤,那么给菜改刀,点火,放菜,放水,上菜等等都是有先后顺序的,总不可能先上菜再给菜改刀吧?那么每个时间就有了优先级(谁是谁的前提事件)
AOV网就是描述这种事件顺序的网络,拓扑排序就是根据优先级进行的排序
特别注意
1.a,(b,c),d、这种情况,也就是b,c同级,那么abcd或acbd都是可行的顺序。
2.拓扑排序必须是有向无环图

AOE网和关键路径
围绕四个问题,点的最早发生时间,点的最迟发生时间,边的最早发生时间,边的最迟发生时间

字符串和多维数组
无编程考点
其他考点:KMP的next数组计算,KMP匹配过程,特殊矩阵地址变换(一般就是围绕等差等比数列,属于概念+高中基础知识,还有行列有限的转换)

树和二叉树

我这次期末必考程序:二叉树后序遍历的逆序。
常考高频:二叉树遍历,树深度,叶子节点树(可以说,就是考了个二叉树遍历,掌握个递归就完了,偶尔还会考考二叉树构造)
其他考点:森林,数,二叉树之间的转换(孩子兄弟表示法)哈夫曼树(合法哈夫曼树的两个判定)线索二叉树(二叉链表,左子右父)树的遍历树的建立(已知中序+前/后序构建二叉树)
不常考考点:并查集,其他表示法

二叉树的构建

struct node
{
    int a;
    node *lc,*rc;
};
class tree
{
    node *root;
public:
    void porder()
    {
    }
    node *creat()
    {
        int a;
        node *p;
        cin>>a;
        if(a=='#')
            p=nullptr;
        else
       {
          p=new node;
          p->a=a;
          p->lc=creat();
          p->rc=creat();
       }
        return p;
    }
    tree()
    {
        root=creat();
    }
};

前序遍历

void porder(node *t)
    {
       if(t==nullptr)
        return;
       else
       {
           cout<<t->a<<endl;
           porder(t->lc);
           porder(t->rc);
       }
    }

中后序略

层序遍历

void lorder()
    {
        node *q[100],*p=nullptr;
        int front1=-1,rear=-1;
        if(root==nullptr)
        {
            return;
        }
        q[++rear]=root;
        while(rear!=front1)
        {
            p=q[++front1];
            cout<<p->a<<endl;
            if(p->lc!=nullptr)
                q[++rear]=p->lc;
            if(p->rc!=nullptr)
                q[++rear]=p->rc;
        }
    }

树深度

 int treed(node *t)
    {
        int lh,rh,max1;
        if(t!=nullptr)
        {
          lh=treed(t->lc);
          rh=treed(t->rc);
          max1=lh>rh?lh:rh;
          return(max1+1);  
        }
        return 0;
    }

来张全家福

struct node
{
    char c;
    node *lc,*rc;
};
class tree
{
private:
    node *root;
public:
    node *creat()
    {
        node *p=nullptr;
        char a;
        cin>>a;
        if(a=='#')
            p=nullptr;
        else
        {
           p=new node;
           p->c=a;
           p->lc=creat();
           p->rc=creat();
        }
        return p;
    }
    node *Root()
    {
        return this->root;
    }
    tree()
    {
       root=creat();
    }
    int treed(node *t)
    {
        int lh=0,rh=0,max1=0;
        if(t==nullptr)
            return 0;
        else
        {
            lh=treed(t->lc);
            rh=treed(t->rc);
            max1=rh>lh?rh:lh;
            return (max1+1);
        }
    }
    void preorder(node *t)
    {
        if(t==nullptr)
            return ;
        else
        {
            cout<<t->c<<endl;
            preorder(t->lc);
            preorder(t->rc);
        }
    }
    void lorder()
    {
        node *q[100],*p=nullptr;
        int front1=-1,rear=-1;
        q[++rear]=root;
        while(rear!=front1)
        {
            p=q[++front1];
            if(p->lc!=nullptr)
                q[++rear]=p->lc;
            if(p->rc!=nullptr)
                q[++rear]=p->rc;
        }
    }
};

栈和队列:
可能涉及到程序:栈和队列的实现
其他考点:括号匹配问题,表达式问题,双端队列和两栈共享空间问题

线性表:
必考程序:单链表的基本操作
其他考点:约瑟夫环,双链表,循环链表

目前尚不熟悉考点:
所有编程考点都再过一遍
四个排序
图的两个存储下的两种遍历(共四个遍历)
二叉树遍历
栈,线性栈,链表栈,共享空间栈
队列,线性队列,链表队列,循环队列,*双端队列(最后有时间就看看)
单链表
老师指出的部分章末习题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值