所在的位置: 数据结构 >> 讨论范畴 >> 数据结构模板

数据结构模板

北京专科手足癣医院 http://www.yidianzixun.com/article/0U3VW1ym?s=yunos

队列的数据结构知识点一般有5个:

FIFO队列

循环队列(模板)

单调队列(模板)

堆(模板)

优先级队列

循环队列

classMyCircularQueue{

//已经使用的元素个数

privateintused=0;

//第一个元素所在位置

privateintfront=0;

//rear是enQueue可在存放的位置

//注意开闭原则

//[front,rear)

privateintrear=0;

//循环队列最多可以存放的元素个数

privateintcapacity=0;

//循环队列的存储空间

privateint[]a=null;

publicMyCircularQueue(intk){

//初始化循环队列

capacity=k;

a=newint[capacity];

}

publicbooleanenQueue(intvalue){

//如果已经放满了

if(isFull()){

returnfalse;

}

//如果没有放满,那么a[rear]用来存放新进来的元素

a[rear]=value;

//rear注意取模

rear=(rear+1)%capacity;

//已经使用的空间

used++;

//存放成功!

returntrue;

}

publicbooleandeQueue(){

//如果是一个空队列,当然不能出队

if(isEmpty()){

returnfalse;

}

//第一个元素取出

intret=a[front];

//注意取模

front=(front+1)%capacity;

//已经存放的元素减减

used--;

//取出元素成功

returntrue;

}

publicintFront(){

//如果为空,不能取出队首元素

if(isEmpty()){

return-1;

}

//取出队首元素

returna[front];

}

publicintRear(){

//如果为空,不能取出队尾元素

if(isEmpty()){

return-1;

}

//注意:这里不能使用rear-1

//需要取模

inttail=(rear-1+capacity)%capacity;

returna[tail];

}

//队列是否为空

publicbooleanisEmpty(){

returnused==0;

}

//队列是否满了

publicbooleanisFull(){

returnused==capacity;

}

}

单调队列

classSolution{

//单调队列使用双端队列来实现

privateArrayDequeIntegerQ=newArrayDequeInteger();

//入队的时候,last方向入队,但是入队的时候

//需要保证整个队列的数值是单调的

//(在这个题里面我们需要是递减的)

//并且需要注意,这里是Q.getLast()val

//如果写成Q.getLast()=val就变成了严格单调递增

privatevoidpush(intval){

while(!Q.isEmpty()Q.getLast()val){

Q.removeLast();

}

//将元素入队

Q.addLast(val);

}

//出队的时候,要相等的时候才会出队

privatevoidpop(intval){

if(!Q.isEmpty()Q.getFirst()==val){

Q.removeFirst();

}

}

classHeap{

privateint[]a=null;

privateintn=0;

//下沉

publicvoidsink(inti){

intj=0;

intt=a[i];

//找到i结点的左子结点

while((j=(i1)+1)n){

//jn-1判断是否有右子结点

//如果有,并且右子结点更大,那么

//j指向右子结点

if(jn-1a[j]a[j+1]){

j++;

}

//如果子结点比t大

//那么t的位置还需要往后排

if(a[j]t){

a[i]=a[j];

i=j;

}else{

//找到了t的位置

//此时t是大于所有的子结点的

break;

}

}

//将t放在找到的位置那里

a[i]=t;

}

//上浮

publicvoidswim(inti){

intt=a[i];

intpar=0;

//如果还存在父结点

while(i0(par=(i-1)1)!=i){

//如果父结点比t值小

if(a[par]t){

a[i]=a[par];

i=par;

}else{

break;

}

}

a[i]=t;

}

publicvoidpush(intv){

//push是先把元素追加到数组尾巴上,然后再执行上浮操作

a[n++]=v;

swim(n-1);

}

publicintpop(){

intret=a[0];

a[0]=a[--n];

sink(0);

returnret;

}

publicintsize(){

returnn;

}

}

链表

classMyLinkedList{

//实现单链表

//1.假设链表中的所有节点都是0-index的。

classListNode{

publicintval=0;

publicListNodenext=null;

publicListNode(){}

publicListNode(intx){

val=x;

}

}

privateListNodedummy=newListNode();

privateListNodetail=dummy;

privateintlength=0;

/**Initializeyourdatastructurehere.*/

publicMyLinkedList(){

}

privateListNodegetPreNode(intindex){

ListNodefront=dummy.next;

ListNodeback=dummy;

for(inti=0;iindex;i++){

back=front;

front=front.next;

}

returnback;

}

//获取链表中第index个节点的值。如果索引无效,则返回-1。

publicintget(intindex){

if(index0

index=length){

return-1;

}

returngetPreNode(index).next.val;

}

//在链表的第一个元素之前添加一个值为val的节点。

//插入后,新节点将成为链表的第一个节点。

publicvoidaddAtHead(intval){

ListNodep=newListNode(val);

p.next=dummy.next;

dummy.next=p;

//NOTEchangetail

if(tail==dummy){

tail=p;

}

length++;

}

//将值为val的节点追加到链表的最后一个元素。

publicvoidaddAtTail(intval){

tail.next=newListNode(val);

tail=tail.next;

length++;

}

//在链表中的第index个节点之前添加值为val的节点。

//1.如果index等于链表的长度,则该节点将附加到链表的末尾。

//2.如果index大于链表长度,则不会插入节点。

//3.如果index小于0,则在头部插入节点。

publicvoidaddAtIndex(intindex,intval){

if(indexlength){

return;

}elseif(index==length){

addAtTail(val);

return;

}elseif(index=0){

addAtHead(val);

return;

}

ListNodepre=getPreNode(index);

ListNodep=newListNode(val);

p.next=pre.next;

pre.next=p;

//NOTE:heretailhasbeenchanged

length++;

}

//如果索引index有效,则删除链表中的第index个节点。

publicvoiddeleteAtIndex(intindex){

if(index0

index=length){

return;

}

ListNodepre=getPreNode(index);

//NOTE:delete-changetail

if(tail==pre.next){

tail=pre;

}

length--;

pre.next=pre.next.next;

}

}

前序遍历

voidpreOrder(TreeNoderoot,ListIntegerans){

//边界处理:如果树为空,那么不需要处理

if(root!=null){

//先访问根结点

ans.add(root.val);

//再分别访问左子树

preOrder(root.left,ans);

//再访问右子树

preOrder(root.right,ans);

}

}

使用栈来实现的前序遍历的代码如下

classSolution{

publicListIntegerpreorderTraversal(TreeNoderoot){

//用来进行递归的栈

StackTreeNodes=newStack();

//用来存放遍历的结果,不算在空间复杂度里面

ListIntegerans=newArrayList();

//开始利用栈来进行遍历

while(root!=null

!s.empty()){

//模拟递归的压栈过程

while(root!=null){

s.push(root);

ans.add(root.val);

root=root.left;

}

//当无法压栈的时候,将root.right进行压栈

root=s.peek();

s.pop();

root=root.right;

}

returnans;

}

}

中序遍历

voidpreOrder(TreeNoderoot,ListIntegerans){

if(root!=null){

//先遍历左子树

preOrder(root.left,ans);

//然后遍历中间的根结点

ans.add(root.val);

//最后遍历右子树

preOrder(root.right,ans);

}

}

采用非递归的中序代码

classSolution{

publicListIntegerinorderTraversal(TreeNoderoot){

StackTreeNodes=newStack();

ListIntegerans=newArrayList();

//注意这里的判断条件,需要root或stack非空

while(root!=null

!s.empty()){

//往左边走,连续入栈,直到不能再走为止

while(root!=null){

s.push(root);

root=root.left;

}

//到达了最左边,把结点弹出来,进行遍历

root=s.peek();

s.pop();

ans.add(root.val);

//转向右子树

root=root.right;

}

//返回遍历的结果

returnans;

}

}

后序遍历

采用递归实现的后序遍历代码模板如下

voidpostOrder(TreeNoderoot,ListIntegerans){

if(root!=null){

//先遍历左子树

postOrder(root.left,ans);

//最后遍历右子树

postOrder(root.right,ans);

//然后遍历中间的根结点

ans.add(root.val);

}

}

采用非递归的后序遍历代码如下

classSolution{

publicListIntegerpostorderTraversal(TreeNodet){

//存放遍历的结果

ListIntegerans=newArrayList();

//pre表示遍历时前面一个已经遍历过的结点

TreeNodepre=null;

StackTreeNodes=newStack();

//如果栈中还有元素,或者当前结点t非空

while(!s.isEmpty()

t!=null){

//顺着左子树走,并且将所有的元素压入栈中

while(t!=null){

s.push(t);

t=t.left;

}

//当没有任何元素可以压栈的时候

//拿栈顶元素,注意这里并不将栈顶元素弹出

//因为在迭代时,根结点需要遍历两次,这里需要判断一下

//右子树是否遍历完毕

t=s.peek();

//如果要遍历当前结点,需要确保右子树已经遍历完毕

//1.如果当前结点右子树为空,那么右子树没有遍历的必要

//需要将当前结点放到ans中

//2.当t.right==pre时,说明右子树已经被打印过了

//那么此时需要将当前结点放到ans中

if(t.right==null

t.right==pre){

//右子树已经遍历完毕,放到ans中。

ans.add(t.val);

//弹栈

s.pop();

//因为已经遍历了当前结点,所以需要更新pre结点

pre=t;

//已经打印完毕。需要设置为空,否则下一轮循环

//还会遍历t的左子树。

t=null;

}else{

//第一次走到t结点,不能放到ans中,因为t的右子树还没有遍历。

//需要将t结点的右子树遍历

t=t.right;

}

}

returnans;

}

}

并查集

classUF{

//并查集数组

int[]F=null;

//记录并查集中集合的个数

intcount=0;

//记录集合中点的个数,比如要知道i所在集合的点有多少个:C[Find(i)]

//注意:这里不能直接使用C[i]

//因为只有根结点的统计才是正确的

int[]Cnt=null;

//并查集的初始化

voidInit(intn)

{

F=newint[n];

Cnt=newint[n];

for(inti=0;in;i++){

F[i]=i;

Cnt[i]=1;

}

count=n;

}

intFind(intx)

{

if(x==F[x]){

returnx;

}

F[x]=Find(F[x]);

returnF[x];

}

voidUnion(intx,inty)

{

intxpar=Find(x);

intypar=Find(y);

//将x所在集合,合并到y所在集合

if(xpar!=ypar){

F[xpar]=ypar;

//y集合里面的个数要增加

Cnt[ypar]+=Cnt[xpar];

count--;

}

}

intSize(inti){returnCnt[Find(i);}

}

预览时标签不可点收录于话题#个上一篇下一篇


转载请注明:http://www.92nongye.com/tlfc/tlfc/204625843.html