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

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

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

  • 链表

    ~链表,就是像铁链一样一节连一节,每节都有自己的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;
     }
 }

 

  • 栈 (先进后出)

    stl库中有栈这个容器,但是一般自己实现(一般情况下,调用栈的空间大小为16MB)

  int stck[maxx],top=0;//栈顶位置
  void push(int a){stack[++top]=a;}//入栈
  int pop(){return stack[--top];}//出栈并返回栈顶
  bool empty(){return top<1;}//栈是否为空

    使用栈模拟递归时,注意入栈顺序 -->逆序入栈,先递归的后入栈
   

  • 队列(先进后出)

 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;
     }
    }
    -----------------------------------华丽分割线--------------------------------
   
    打了三个半小时,发现自己之前漏了好多知识点
 总结真的有用,嗯!
   
 

 

 

 

 


       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值