九万五千亿的22.1.20的队列,栈,二叉树的笔记

队列的实现

队列是很常见的数据结构,它的存取方式是“先进先出”。生活中的排队,就是队列的原型

队列有两种实现方式:链队列和循环队列。

  • 链队列实际上和单向链表一样,用指针把各个结点连接起来。

  • 循环队列使用一组连续的存储单元依次存放队列元素,用指针 head指示队列头元素,rear指向尾元素。当 head 和 rear走到底时,下一步回到开始的位置,从而在这组连续空间内循环。设计成循环能解决溢出问题。

手写循环队列

#define MAXQSIZE 100003        //自定义队列大小
struct myqueue{
    int data[MAXQSIZE];      //分配静态空间
    int head;                  //队头,指向队头的元素
    int rear;                //队尾,指向下一个可以放元素的空位置
    bool init(){             //初始化
        head = rear = 0;
        return true;
    }
    int size(){              //返回队列长度
        return (rear - head + MAXQSIZE) % MAXQSIZE;
    }
    bool empty(){            //判断队列是否为空
        if(size()==0) return true;
        else          return false;
    }
    bool push(int e){        //队尾插入新元素。新的rear指向下一个空的位置
         if((rear + 1) % MAXQSIZE == head ) return false; //队列满
         data[rear] = e;
         rear = (rear + 1) % MAXQSIZE;
         return true;
    }
    bool pop(int &e){        //删除队头元素,并返回它
         if(head == rear) return false;   //队列空
         e = data[head];
         head = (head + 1) % MAXQSIZE;
         return true;
    }
    int front(){            //返回队首,但是不删除
        return data[head];
    }
};>

STL queue

queue<Type> q;      //定义队列,Type为数据类型,如int,float,char等
q. push(item);        //把item放进队列
q.front();         //返回队首元素,但不会删除
q.pop();        //删除队首元素
q.back();        //返回队尾元素
q.size();         //返回元素个数
q.empty();         //检查队列是否为空 

栈的用法以及实现

栈只有唯一的一个出入口,从这个口进入,也从这个口出来,而队列有一个入口和一个出口,这是栈和队列最大的区别。栈的代码比队列的代码更简单,栈像一个只有一个门的房子,而队列这个房子有前门和后门。

那么栈该如何实现呢?

在这里看一下栈的基本用法:

  1. push(): 向栈内压入一个成员;

  2. pop(): 从栈顶弹出一个成员;

  3. empty(): 如果栈为空返回true,否则返回false;

  4. top(): 返回栈顶,但不删除成员;

  5. size(): 返回栈内元素的大小;

编程中常用的递归,在系统中是用栈来保存现场的。栈需要用空间存储,如果栈的深度太大,或者存进栈的数组太大,那么总数会超过系统为栈分配的空间,就会爆栈导致栈溢出。做题需要使用栈时,直接用STL stack或者自己写栈。

下面为自己手写的栈

const int N = 100100;   //定义栈的大小
struct mystack{
    int a[N];                           //存放栈元素
    int t = -1;                          //栈顶位置
    void push(int x){ a[++t] = x; }      //送入栈
    int top()       { return a[t]; }     //返回栈顶元素
    void pop()       { t--;         }     //弹出栈顶
    int empty()      { return t==0?1:0;}  //返回1表示空
}; 

下面是STL stack

#include<iostream>
#include<stack>
using namespace std;
​
int main()
{
    stack <int>stk;
    //入栈
    for(int i=0;i<50;i++){
        stk.push(i);
    }
    cout<<"栈的大小:"<<stk.size()<<endl;
    while(!stk.empty())
    {
        cout<<stk.top()<<endl;
        stk.pop();
    }
    cout<<"栈的大小:"<<stk.size()<<endl;
    return 0;
}
​

二叉树的初步和实现

二叉树是每个结点最多有两个子树的树结构,即结点的度最大为2。通常子树被称作”左子树”和”右子树”。二叉树是一个连通的无环图。

二叉树是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:(1)、空二叉树;(2)、只有一个根结点的二叉树;(3)、只有左子树;(4)、只有右子树;(5)、完全二叉树。

二叉树类型:

(1)、满二叉树:深度(层数)为k,且有2^k-1个结点的二叉树。这种树的特点是每一层上的结点数都是最大结点数。即除了叶结点外每一个结点都有左右子树且叶节点都处在最低层。

(2)、完全二叉树:除最后一层外,其余层都是满的,并且最后一层或者是满的,或者是在右边缺少连续若干节点,即叶子结点都是从左到右依次排布。具有n个节点的完全二叉树的深度为floor(log(2n))+1。深度为k的完全二叉树,至少有2^(k-1)个结点,至多有(2^k)-1个结点。

完全二叉树编写序号一般从1开始, Lchild/2=parent,孩子节点除以二等于父节点

(3)、平衡二叉树:又被称为AVL树,它是一颗二叉排序树,且具有以下性质:它是一颗空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一颗平衡二叉树。

遍历二叉树:

按一定的规则和顺序走遍二叉树的所有结点,使每一个结点都被访问一次,而且只被访问一次。对一颗二叉树的遍历有四种情况:先序遍历、中序遍历、后序遍历、按层遍历。

(1)、先序遍历:先访问根结点,再先序遍历左子树,最后再先序遍历右子树,即先访问根结点-------左子树------右子树。

void preorder (node *root){ 
     cout << root ->value;        //输出
     preorder (root -> lson);      //递归左子树
     preorder (root -> rson);      //递归右子树
}

(2)、中序遍历:先中序遍历左子树,然后再访问根结点,最后再中序遍历右子树,即先访问左子树------根结点------右子树。

void inorder (node *root){ 
     inorder (root -> lson);      //递归左子树
     cout << root ->value;         //输出
     inorder (root -> rson);      //递归右子树
}

(3)、后序遍历:先后序遍历左子树,然后再后序遍历右子树,最后再访问根结点,即先访问左子树------右子树------根结点。

void postorder (node *root){ 
     postorder (root -> lson);      //递归左子树
     postorder (root -> rson);      //递归右子树
     cout << root ->value;        //输出
}

如果知道「中序遍历+先序遍历」的结果,或者「中序遍历+后序遍历」的结果,也都能确定一棵树。但是,如果不知道中序遍历,只有「先序遍历+后序遍历」的结果,则不能确定一棵二叉树。

对于二叉树的一个结点,我们通常要存储结点的值、左右子结点。在算法竞赛中,为了编码简单,加快速度,一般用静态数组来实现二叉树。比如定义一个大小为 NN 的结构体数组,用它来存一棵二叉树。代码如下:

struct Node{              //静态二叉树
   char value;
   int lson, rson;        //左右孩子,编码时把lson简写为ls或者l
}tree[N];                 //编码时把tree简写为t

再次特别说明,二叉树并不明白,需要进一步详解

typedef struct treeNode{
char data;
struct treeNode *Lchild;
struct treeNode *Rchild;
}TREE,*LPTREE;
//别名中lp一般表示是指针别名
LPTREE createNode(char data)
{
LPTREE newNode=(LPTREE)malloc(sizeof(TREE));
newNode->data=data;
newNode->Lchild=NULL;
newNode->Rchild=NULL;
return newNode;
​
}
//没有规律的树
void insertNode(LPTREE parentNode,LPTREE Lchild,LPTREE R child)
{
parentNode->Lchild=Lchild;
parentNode->Rchild=Rchild;
}
//打印当前节点中的元素
void printcurnodedata(LPTREE curData)
{
printf("%c\t",curData->data);
}
//递归法
//先序
void preOrder(LPTREE root)
{
if(root!=NULL)
{
printfcurnodedata(root);
preOrder(root->Lchild);
preOrder(root->Rchild);
}
}
int main()
{
//死板的创建过程,无实际作用
LPTREE A=createNode('A');
LPTREE B=createNode('B');
LPTREE C=createNode('C');
LPTREE D=createNode('D');
LPTREE E=createNode('E');
LPTREE F=createNode('F');
insertNode(A,B,C);
insertNode(B,D,NULL);
insertNode(D,NULL,G);
insertNode(C,E,F);
return 0;
​
}

![image-20220121102754766](C:\Users\86150\AppData\Roaming\Typora\typora-user-images\image-20220121102754766.png)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值