集训心得2(基本数据结构)

今天讲讲基本数据结构部分啊,比较难理解,多看几遍好多了,能看懂,但不会写。

本来想把基本数据结构打完,看来是我想多了。。。

    1.链表
    ~链表,就是像铁链一样一节连一节,每节都有自己的value和next,代码如下:
 struct node
 {
     int value,next;
 } a[MAX];
 int insert(int p,int q)//把q元素插到第p个元素后
    {
     top++;//链表中元素个数
  a[top].value=q;
  a[top].next=a[p].next;
  a[p].next=top;
 }
    //以下是遍历
 int temp=head;
 while(temp)
 {
  cout<<a[temp].value;
  temp=a[temp].next;//查找下一个
 }
    ~循环链表 与单链表的区别就是最后一个元素的next指向head
 ~双向链表 差别不大 就是每个元素不仅有next还有prev(前驱后继)
 举个例子更好理解
 例: 将元素p插入升序链表中
    void insert(int p)
 {
  int now,last;
  a[++top].value=p;
  if(a[head].value>p)//
  {
   a[top].next=head;
   a[head].prev=top;
   head=top;
  }
  else
  {
   now=head;
   while()(a[now].value<p)&&(now<top))
   {
    last=now;
    now=a[now].next;
   }
   a[last].next=top;
   a[top].prev=last;
   a[top].next=now;
   a[now].prev=top;
  }
 }

    2.栈 (先进后出)
    stl库中有栈这个容器,但是一般自己实现(一般情况下,调用栈的空间大小为16MB)
    int stck[maxx],top=0;//栈顶位置
 void push(int a)//入栈
 {
  stack[++top]=a;
 }
    int pop()//出栈
    {
     return stack[--top];
    }
    bool empty()//栈空的条件
    {
     return top<1;
    }
    使用栈模拟递归时,注意入栈顺序 -->逆序入栈,先递归的后入栈
   
    3.队列(先进后出)
 int a[maxx],head=0,tail=0;//首个元素  尾部元素
    void push(int a)
 {
  a[++tail]=a;
 }
    int pop()
    {
     return a[head++];
    }
    bool empty()
    {
     return head>tail;
    }
    ~循环队列 相对以上链状队列节省很大空间
  int a[N],head=1,tail=1;
    void push(int a)
 {
  a[tail]=a;
  tail=(tail+1)%N;
 }
    int pop()
    {
     int t=a[head];
     head=(head+1)%N;
     return t;
    }
    bool empty()//队空或队满的条件
    {
     return head==tail;
    }
    此处empty有必要说一下
 区别队空队满的方法个人觉得比较好理解的一种:
        在进出队时记录元素个数,这样直接检查元素个数就能判断了;
 ~单调队列
     表示没搞懂单调队列和一般队列的特殊区别,感觉没差多少
 4.树和二叉树
   对于树的概念就不多说了,自行查提高篇P77;
 ~二叉树的链表存储法
 struct node
 {
  int value;
  int leftchild,rightchild;
  int id;               //结点编号
  int parent;           //指向父结点
 }a[N];
 int top=0,head=0;
    #define NEM(p) p=&a[++top];   //懒人用的宏定义
    p.leftchild=__;
    p.rightchild=__;
    p.value=__;
    ~完全二叉树的一维数组存储法(找度娘)
    ~二叉树的遍历(我们默认二叉树左子树的优先级高于右子数)
     其实三种遍历的代码差不多
  1)前序遍历
     void preorder(int p)
     {
      if(p==0) return;//处理结点p
      cout<<a[p].value;
      preorder(a[p].leftchild);
      preorder(a[p].rughtchild);
     }
  2)中序遍历
  void inorder(int p)
  {
   if(p==0) return;
   inorder(a[p].leftchild);
   cout<<a[p].value;
   inorder(a[p].rightchild);
  }
  3)后续遍历
  void postorder(int p)
  {
   if(p==0) return;
   postorder(a[p].leftchild);
   cout<<a[p].value;
   postorder(a[p].rightchild);
  }
     ~二叉树重建
  1)输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。    
  
    
 

      上代码:
   void postorder(int n,int la,int lb)
   {
    if(n<=0) return;
    for(int i=la;i<=la+n-1;i++)
    if(a[i]==b[lb])
    {
     postorder(i-la,la,lb+1);
     postorder(la+n-1-i,i+1,lb+i-la+1);
     cout<<b[lb];
     return;
    }
   }
    2)给出 后序遍历 中序遍历 求前序遍历
      其实道理差不多
   void postorder(int n,int la,int lb)
   {
    if(n<=0) return;
    for(int i=la;i<=la+n-1;i++)
    if(a[i]==b[lb])
    {
     cout<<b[lb];//此处较上文 位置改变
     postorder(i-la,la,lb+1);
     postorder(la+n-1-i,i+1,lb+i-la+1);
     
     return;
    }
   }
    3) 求中序 (有多组解)
    ~ 求二叉树的直径 (暂时不懂,P80页)
    5.并查集
  struct node
  {
   int parent,value;
  } set[MAX];
   
 int getfather(int x)//递归版本(数据太大会爆栈)
 {
  if(set[x].father==x) return x;
  else
  {
   set[x].parent=getfather(set[x].parent);
   return set[x].parent;
  }
  //下面是问号表达式的写法,更简洁
  //return (set[x].parent==x)? x:(set[x].parent=getfather(set[x].parent));
 }
    
    int getfather(int x)//非递归版本
    {
     int y=x;
     while(set[y].parent!=y)         //寻找父结点
         y=set[y].parent;
     while(x!=y)                     //路径压缩,把途中经过的结点的父亲都改为y
     {
      int tmp=set[x].parent;
      set[x].parent=y;
      x=tmp;
     }
     return y;
    }
   
    void Union(int x,int y)              //小写union是关键词
    {
     x=getfather(x);y=getfather(y);   //寻找各自根节点
     if(x==y) return;
     set[y].parent=x;                 //若不在同个集合,合并
    }
   
    void init(int cnt)                   //初始化并查集,cnt为元素个数
    {
     for(int i=1;i<=cnt;i++)
     {
      set[i].parent=i;
      set[i].value=0;
     }
    }
    -----------------------------------华丽分割线--------------------------------
   
    打了三个半小时,发现自己之前漏了好多知识点
 总结真的有用,嗯!
   
 


       

猜你喜欢

转载自blog.csdn.net/fm19870504/article/details/80529802