数据结构_基础结构
鏈表
鏈表是一種數(shù)據(jù)結(jié)構(gòu),相對(duì)于數(shù)組而言,插入和刪除的開銷比較小,而查找的代價(jià)較大.以下我們實(shí)現(xiàn)雙向鏈表:
public class MyList<T> {private Node<T> head;private Node<T> tail;private int size;//初始化頭結(jié)點(diǎn)和尾節(jié)點(diǎn)public MyList(){head=new Node<T>(null, null, tail);tail=new Node<T>(null, head, null);}//獲得大小public int size(){return size;}//增加方法public void add(T x){this.addBefore(tail, x);}public void addBefore(int index,T x){this.addBefore(this.getNode(index), x);}public void addBefore(Node<T> p,T x){Node<T> newNode=new Node<T>(x, p.prev, p);newNode.prev.next=newNode;p.prev=newNode;size++;}//查找方法 效率應(yīng)該高點(diǎn)public Node<T> getNode(int index){Node<T> p;if(index<size()/2){p=head.next;for(int i=0;i<index;i++){p=p.next;}}else{p=tail;for(int i=size();i>index;i--){p=p.prev;}}return p;}//刪除 public T remove(int index){return remove(this.getNode(index));}public T remove(Node<T> p){p.next.prev=p.prev;p.prev.next=p.next;size--;return p.data;}//修改public void set(int index,T newData){Node<T> p=this.getNode(index);p.data=newData;}//顯示全部public void show(){if(size()>0){Node<T> p=head.next;while(p!=tail){System.out.println(p.data);p=p.next;}}}//節(jié)點(diǎn)類private static class Node<T>{public T data;public Node<T> prev;public Node<T> next;public Node(T d,Node<T> p,Node<T> n){data=d;prev=p;next=n;}}}在我寫的這個(gè)雙向鏈表中頭節(jié)點(diǎn)head和尾節(jié)點(diǎn)tail是空出來的,不存放任何數(shù)據(jù).若是要改造成雙向循環(huán)鏈表的話就不合適了,比如最后一個(gè)元素要next三下越過tail和head才循環(huán)到第一個(gè)元素.
于是稍作改造(注意空指針),雙向循環(huán)鏈表:
棧
棧Stack是一個(gè)表,先進(jìn)后出,有兩種實(shí)現(xiàn)方式:由鏈表或者數(shù)組來實(shí)現(xiàn).這里我們選用數(shù)組實(shí)現(xiàn)做例子,比較簡單:
package com.fredal.structure;public class MyStack<T> {// Java 不支持泛型數(shù)組,如需使用,請(qǐng)使用Java提供的容器private Object[] stack;// 棧的默認(rèn)初始大小private static final int INIT_SIZE = 2;// 棧頂索引private int index;public MyStack() {stack = new Object[INIT_SIZE];index = -1;}/*** 構(gòu)造方法* * @param initSize* 棧的初始大小*/public MyStack(int initSize) {if (initSize < 0) {throw new IllegalArgumentException();}stack = new Object[initSize];index = -1;}/*** 出棧操作* * @return 棧頂對(duì)象*/public T pop() {if (!isEmpty()) {T temp = peek();stack[index--] = null;return temp;}return null;}/*** 入棧操作* * @param obj* 等待入棧的對(duì)象*/public void push(T obj) {if (isFull()) {Object[] temp = stack;// 擴(kuò)容操作,和arraylist的一樣,如果棧滿,則創(chuàng)建空間為當(dāng)前棧空間兩倍的棧stack = new Object[2 * stack.length];System.arraycopy(temp, 0, stack, 0, temp.length);}stack[++index] = obj;}/*** 查看棧頂對(duì)象* * @return 棧頂對(duì)象*/public T peek() {if (!isEmpty()) {return (T) stack[index];}return null;}/*** 查看棧是否為空* * @return 如果棧為空返回true,否則返回false*/public boolean isEmpty() {return index == -1;}/*** 查看棧是否滿* * @return 如果棧滿返回true,否則返回false*/public boolean isFull() {return index >= stack.length - 1;} }應(yīng)用的比較多的一個(gè)是檢測(cè)平衡符號(hào),這個(gè)比較簡單,就是按順序push按順序pop看看是否相同.另外一個(gè)是逆波蘭表達(dá)式,寫一段代碼,包括中序表達(dá)式轉(zhuǎn)化為逆波蘭式,以及逆波蘭式的計(jì)算:
package com.fredal.structure;import java.util.ArrayList; import java.util.List; import java.util.Stack;public class Nbl {private static Stack s1 = new Stack();// 逆波蘭表達(dá)式的棧private static Stack s2 = new Stack();// 運(yùn)算棧//將字符串轉(zhuǎn)化成中序listpublic static List<String> format(String s) {List<String> ls = new ArrayList<String>();// 存儲(chǔ)中序表達(dá)式int i = 0;String str;char c;do {if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {ls.add("" + c);i++;} else {str = "";while (i < s.length() && (c = s.charAt(i)) >= 48&& (c = s.charAt(i)) <= 57) {str += c;i++;}ls.add(str);}} while (i < s.length());return ls;}//將中序表達(dá)式轉(zhuǎn)化為逆波蘭式public static List<String> parse(List<String> ls) {List<String> lss = new ArrayList<String>();for (String ss : ls) {if (ss.matches("\\d+")) {lss.add(ss);// 不是運(yùn)算符就加入list} else if (ss.equals("(")) {s1.push(ss);//碰到"("直接進(jìn)棧} else if(ss.equals(")")){while(!s1.peek().equals("(")){//將直到"("的符號(hào)全彈出lss.add((String) s1.pop());//加入list}s1.pop();//彈出"("}else{while(s1.size()!=0&&getValue((String) s1.peek())>=getValue(ss)){//比它優(yōu)先級(jí)高的全彈出lss.add((String) s1.pop());}s1.push(ss);}}while(s1.size()!=0){//結(jié)束之后全部彈出lss.add((String) s1.pop()); }return lss;}//獲取運(yùn)算符優(yōu)先級(jí)private static int getValue(String s) {if (s.equals("+")) {return 1;} else if (s.equals("-")) {return 1;} else if (s.equals("*")) {return 2;} else if (s.equals("/")) {return 2;}return 0;}// 對(duì)逆波蘭表達(dá)式進(jìn)行求值public static int calculate(List<String> ls) {for (String s : ls) {if (s.matches("\\d+")) {s2.push(s);// 不是運(yùn)算符就入棧} else {int b = Integer.parseInt((String) s2.pop());int a = Integer.parseInt((String) s2.pop());if (s.equals("+")) {a = a + b;} else if (s.equals("-")) {a = a - b;} else if (s.equals("*")) {a = a * b;} else if (s.equals("/")) {a = a / b;}s2.push("" + a);}}return Integer.parseInt((String) s2.pop());} }隊(duì)列
隊(duì)列(queue)也是表,使用隊(duì)列時(shí)插入在一端進(jìn)行而刪除在另一端進(jìn)行.
基本操作是enqueue入隊(duì),在表的末端插入元素.dequeue出隊(duì),刪除并返回表的開頭.
用數(shù)組實(shí)現(xiàn)隊(duì)列會(huì)有潛在問題,就是隊(duì)列滿了之后在入隊(duì)一次back的下標(biāo)會(huì)指向不存在的位置,解決這個(gè)問題我們用循環(huán)隊(duì)列的方式.
樹
先說二叉樹,二叉樹表示每個(gè)節(jié)點(diǎn)都不能有多于兩個(gè)的兒子.二叉樹的一個(gè)重要應(yīng)用是二叉排序樹ADT:
package com.fredal.structure;public class MyTree<T extends Comparable<T>> {// 節(jié)點(diǎn)類private static class BNode<T> {T element;BNode<T> left;BNode<T> right;public BNode(T element) {this(element, null, null);}public BNode(T element, BNode<T> lt, BNode<T> rt) {this.element = element;left = lt;right = rt;}}// 插入節(jié)點(diǎn)之后public BNode<T> insert(T x, BNode<T> t) {if (t == null) {return new BNode<T>(x, null, null);}int result = x.compareTo(t.element);if (result < 0)t.left = insert(x, t.left);else if (result > 0)t.right = insert(x, t.right);return t;}// 刪除public BNode<T> remove(T x, BNode<T> t) {if (t == null)return t;int result = x.compareTo(t.element);if (result < 0)t.left = remove(x, t.left);else if (result > 0)t.right = remove(x, t.right);else if (t.left != null && t.right != null) {// 找到了 兩個(gè)孩子t.element = findMin(t.right).element;// 雖然是奇怪的刪除策略t.right = remove(t.element, t.right);} else// 找到了 一個(gè)孩子或沒有孩子t = (t.left != null) ? t.left : t.right;return t;}// 尋找最小值public BNode<T> findMin(BNode<T> t) {if (t == null)return null;else if (t.left == null)return t;return findMin(t.left);}// 尋找最大值public BNode<T> findMax(BNode<T> t) {if (t == null)return null;else if (t.right == null)return t;return findMax(t.right);}// 獲得樹的高度public int getHeight(BNode<T> t) {int a = 0;int b = 0;if (t.left != null)a = getHeight(t.left);if (t.right != null)b = getHeight(t.right);return (a > b ? a : b) + 1;}// 是否包含某個(gè)元素public boolean contains(T x, BNode<T> t) {if (t == null)return false;int result = x.compareTo(t.element);if (result < 0)return contains(x, t.left);else if (result > 0)return contains(x, t.right);elsereturn true;}// 顯示 中序遍歷了public void show(BNode<T> t) {if (t.left != null)show(t.left);System.out.println(t.element);if (t.right != null)show(t.right);} }還有一個(gè)就是所謂的表達(dá)式樹,一個(gè)正常的表達(dá)式構(gòu)建的表達(dá)式樹如果采取中序遍歷就是得到正常的表達(dá)式,如果采取后序遍歷呢就會(huì)產(chǎn)生上一節(jié)說的那個(gè)逆波蘭表達(dá)式,也叫后綴表達(dá)式.
基本上這個(gè)樹的作用就是把后序表達(dá)式變成中序表達(dá)式,之前那段代碼逆作用..
用后綴表達(dá)式構(gòu)建樹,再中序遍歷之
表達(dá)式樹確實(shí)是這樣的,中序遍歷也沒錯(cuò),不過要變成正常的表達(dá)式仍然是不夠的,還需要考慮優(yōu)先級(jí)去加括號(hào),偷懶方法當(dāng)然是全部加上括號(hào),這兒不寫了.
然后寫一下多叉樹的實(shí)現(xiàn)吧,這兒寫習(xí)慣了就給node外面加了一層包裝類,這樣添加的時(shí)候還是比較麻煩的,待優(yōu)化吧.
散列
散列也叫哈希,會(huì)遇到散列沖突問題,解決沖突最常用的是分離鏈接法,簡單來說就是將散列到同一個(gè)值的所有元素都插入到一個(gè)鏈表中去,來實(shí)現(xiàn)吧.
package com.fredal.structure;import java.util.LinkedList; import java.util.List;public class MyHashTable<T> {private static final int DEFAULT_SIZE=100;private int size;private List<T>[] lists;public MyHashTable(int size){this.size=size;lists=new LinkedList[size];//初始化鏈表數(shù)組for (int i = 0; i < lists.length; i++) {lists[i]=new LinkedList<T>();}}public MyHashTable(){this(DEFAULT_SIZE);}private int myHash(T x){int hashVal=x.hashCode();hashVal%=lists.length;if(hashVal<0){hashVal+=lists.length;}return hashVal;}//是否包含 使用自帶的就好 ~public boolean contains(T x){List<T> list=lists[myHash(x)];return list.contains(x);}//插入方法public void insert(T x){List<T> list=lists[myHash(x)];if(!list.contains(x)){list.add(x);size++;}}//移除方法public void remove(T x){List<T> list=lists[myHash(x)];if(list.contains(x)){list.remove(x);size--;}} }這里并沒有考慮再散列,因?yàn)閳?chǎng)景不復(fù)雜,再散列以后再談.
還有一種散列表叫探測(cè)散列表,也以后再說...
堆
堆也叫優(yōu)先隊(duì)列,是允許至少下列兩種操作的數(shù)據(jù)結(jié)構(gòu),插入和刪除并返回最小值.插入(insert)相當(dāng)于enqueue(入隊(duì)),而刪除最小值(deleteMin)則等價(jià)于隊(duì)列運(yùn)算dequeue(出隊(duì)).
我們要講的叫二叉堆,除了是一顆完整二叉樹外還要保持其堆序性質(zhì).例如最小二叉堆即,最小元在根上,而任意節(jié)點(diǎn)都小于它的所有后裔.
我們通過代碼模擬二叉堆
堆的應(yīng)用有許多,堆排序是最重要的之一,我們?cè)诤竺鏁?huì)講到.
鏈表
鏈表是一種數(shù)據(jù)結(jié)構(gòu),相對(duì)于數(shù)組而言,插入和刪除的開銷比較小,而查找的代價(jià)較大.以下我們實(shí)現(xiàn)雙向鏈表:
public class MyList<T> {private Node<T> head;private Node<T> tail;private int size;//初始化頭結(jié)點(diǎn)和尾節(jié)點(diǎn)public MyList(){head=new Node<T>(null, null, tail);tail=new Node<T>(null, head, null);}//獲得大小public int size(){return size;}//增加方法public void add(T x){this.addBefore(tail, x);}public void addBefore(int index,T x){this.addBefore(this.getNode(index), x);}public void addBefore(Node<T> p,T x){Node<T> newNode=new Node<T>(x, p.prev, p);newNode.prev.next=newNode;p.prev=newNode;size++;}//查找方法 效率應(yīng)該高點(diǎn)public Node<T> getNode(int index){Node<T> p;if(index<size()/2){p=head.next;for(int i=0;i<index;i++){p=p.next;}}else{p=tail;for(int i=size();i>index;i--){p=p.prev;}}return p;}//刪除 public T remove(int index){return remove(this.getNode(index));}public T remove(Node<T> p){p.next.prev=p.prev;p.prev.next=p.next;size--;return p.data;}//修改public void set(int index,T newData){Node<T> p=this.getNode(index);p.data=newData;}//顯示全部public void show(){if(size()>0){Node<T> p=head.next;while(p!=tail){System.out.println(p.data);p=p.next;}}}//節(jié)點(diǎn)類private static class Node<T>{public T data;public Node<T> prev;public Node<T> next;public Node(T d,Node<T> p,Node<T> n){data=d;prev=p;next=n;}}}在我寫的這個(gè)雙向鏈表中頭節(jié)點(diǎn)head和尾節(jié)點(diǎn)tail是空出來的,不存放任何數(shù)據(jù).若是要改造成雙向循環(huán)鏈表的話就不合適了,比如最后一個(gè)元素要next三下越過tail和head才循環(huán)到第一個(gè)元素.
于是稍作改造(注意空指針),雙向循環(huán)鏈表:
棧
棧Stack是一個(gè)表,先進(jìn)后出,有兩種實(shí)現(xiàn)方式:由鏈表或者數(shù)組來實(shí)現(xiàn).這里我們選用數(shù)組實(shí)現(xiàn)做例子,比較簡單:
package com.fredal.structure;public class MyStack<T> {// Java 不支持泛型數(shù)組,如需使用,請(qǐng)使用Java提供的容器private Object[] stack;// 棧的默認(rèn)初始大小private static final int INIT_SIZE = 2;// 棧頂索引private int index;public MyStack() {stack = new Object[INIT_SIZE];index = -1;}/*** 構(gòu)造方法* * @param initSize* 棧的初始大小*/public MyStack(int initSize) {if (initSize < 0) {throw new IllegalArgumentException();}stack = new Object[initSize];index = -1;}/*** 出棧操作* * @return 棧頂對(duì)象*/public T pop() {if (!isEmpty()) {T temp = peek();stack[index--] = null;return temp;}return null;}/*** 入棧操作* * @param obj* 等待入棧的對(duì)象*/public void push(T obj) {if (isFull()) {Object[] temp = stack;// 擴(kuò)容操作,和arraylist的一樣,如果棧滿,則創(chuàng)建空間為當(dāng)前棧空間兩倍的棧stack = new Object[2 * stack.length];System.arraycopy(temp, 0, stack, 0, temp.length);}stack[++index] = obj;}/*** 查看棧頂對(duì)象* * @return 棧頂對(duì)象*/public T peek() {if (!isEmpty()) {return (T) stack[index];}return null;}/*** 查看棧是否為空* * @return 如果棧為空返回true,否則返回false*/public boolean isEmpty() {return index == -1;}/*** 查看棧是否滿* * @return 如果棧滿返回true,否則返回false*/public boolean isFull() {return index >= stack.length - 1;} }應(yīng)用的比較多的一個(gè)是檢測(cè)平衡符號(hào),這個(gè)比較簡單,就是按順序push按順序pop看看是否相同.另外一個(gè)是逆波蘭表達(dá)式,寫一段代碼,包括中序表達(dá)式轉(zhuǎn)化為逆波蘭式,以及逆波蘭式的計(jì)算:
package com.fredal.structure;import java.util.ArrayList; import java.util.List; import java.util.Stack;public class Nbl {private static Stack s1 = new Stack();// 逆波蘭表達(dá)式的棧private static Stack s2 = new Stack();// 運(yùn)算棧//將字符串轉(zhuǎn)化成中序listpublic static List<String> format(String s) {List<String> ls = new ArrayList<String>();// 存儲(chǔ)中序表達(dá)式int i = 0;String str;char c;do {if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {ls.add("" + c);i++;} else {str = "";while (i < s.length() && (c = s.charAt(i)) >= 48&& (c = s.charAt(i)) <= 57) {str += c;i++;}ls.add(str);}} while (i < s.length());return ls;}//將中序表達(dá)式轉(zhuǎn)化為逆波蘭式public static List<String> parse(List<String> ls) {List<String> lss = new ArrayList<String>();for (String ss : ls) {if (ss.matches("\\d+")) {lss.add(ss);// 不是運(yùn)算符就加入list} else if (ss.equals("(")) {s1.push(ss);//碰到"("直接進(jìn)棧} else if(ss.equals(")")){while(!s1.peek().equals("(")){//將直到"("的符號(hào)全彈出lss.add((String) s1.pop());//加入list}s1.pop();//彈出"("}else{while(s1.size()!=0&&getValue((String) s1.peek())>=getValue(ss)){//比它優(yōu)先級(jí)高的全彈出lss.add((String) s1.pop());}s1.push(ss);}}while(s1.size()!=0){//結(jié)束之后全部彈出lss.add((String) s1.pop()); }return lss;}//獲取運(yùn)算符優(yōu)先級(jí)private static int getValue(String s) {if (s.equals("+")) {return 1;} else if (s.equals("-")) {return 1;} else if (s.equals("*")) {return 2;} else if (s.equals("/")) {return 2;}return 0;}// 對(duì)逆波蘭表達(dá)式進(jìn)行求值public static int calculate(List<String> ls) {for (String s : ls) {if (s.matches("\\d+")) {s2.push(s);// 不是運(yùn)算符就入棧} else {int b = Integer.parseInt((String) s2.pop());int a = Integer.parseInt((String) s2.pop());if (s.equals("+")) {a = a + b;} else if (s.equals("-")) {a = a - b;} else if (s.equals("*")) {a = a * b;} else if (s.equals("/")) {a = a / b;}s2.push("" + a);}}return Integer.parseInt((String) s2.pop());} }隊(duì)列
隊(duì)列(queue)也是表,使用隊(duì)列時(shí)插入在一端進(jìn)行而刪除在另一端進(jìn)行.
基本操作是enqueue入隊(duì),在表的末端插入元素.dequeue出隊(duì),刪除并返回表的開頭.
用數(shù)組實(shí)現(xiàn)隊(duì)列會(huì)有潛在問題,就是隊(duì)列滿了之后在入隊(duì)一次back的下標(biāo)會(huì)指向不存在的位置,解決這個(gè)問題我們用循環(huán)隊(duì)列的方式.
樹
先說二叉樹,二叉樹表示每個(gè)節(jié)點(diǎn)都不能有多于兩個(gè)的兒子.二叉樹的一個(gè)重要應(yīng)用是二叉排序樹ADT:
package com.fredal.structure;public class MyTree<T extends Comparable<T>> {// 節(jié)點(diǎn)類private static class BNode<T> {T element;BNode<T> left;BNode<T> right;public BNode(T element) {this(element, null, null);}public BNode(T element, BNode<T> lt, BNode<T> rt) {this.element = element;left = lt;right = rt;}}// 插入節(jié)點(diǎn)之后public BNode<T> insert(T x, BNode<T> t) {if (t == null) {return new BNode<T>(x, null, null);}int result = x.compareTo(t.element);if (result < 0)t.left = insert(x, t.left);else if (result > 0)t.right = insert(x, t.right);return t;}// 刪除public BNode<T> remove(T x, BNode<T> t) {if (t == null)return t;int result = x.compareTo(t.element);if (result < 0)t.left = remove(x, t.left);else if (result > 0)t.right = remove(x, t.right);else if (t.left != null && t.right != null) {// 找到了 兩個(gè)孩子t.element = findMin(t.right).element;// 雖然是奇怪的刪除策略t.right = remove(t.element, t.right);} else// 找到了 一個(gè)孩子或沒有孩子t = (t.left != null) ? t.left : t.right;return t;}// 尋找最小值public BNode<T> findMin(BNode<T> t) {if (t == null)return null;else if (t.left == null)return t;return findMin(t.left);}// 尋找最大值public BNode<T> findMax(BNode<T> t) {if (t == null)return null;else if (t.right == null)return t;return findMax(t.right);}// 獲得樹的高度public int getHeight(BNode<T> t) {int a = 0;int b = 0;if (t.left != null)a = getHeight(t.left);if (t.right != null)b = getHeight(t.right);return (a > b ? a : b) + 1;}// 是否包含某個(gè)元素public boolean contains(T x, BNode<T> t) {if (t == null)return false;int result = x.compareTo(t.element);if (result < 0)return contains(x, t.left);else if (result > 0)return contains(x, t.right);elsereturn true;}// 顯示 中序遍歷了public void show(BNode<T> t) {if (t.left != null)show(t.left);System.out.println(t.element);if (t.right != null)show(t.right);} }還有一個(gè)就是所謂的表達(dá)式樹,一個(gè)正常的表達(dá)式構(gòu)建的表達(dá)式樹如果采取中序遍歷就是得到正常的表達(dá)式,如果采取后序遍歷呢就會(huì)產(chǎn)生上一節(jié)說的那個(gè)逆波蘭表達(dá)式,也叫后綴表達(dá)式.
基本上這個(gè)樹的作用就是把后序表達(dá)式變成中序表達(dá)式,之前那段代碼逆作用..
用后綴表達(dá)式構(gòu)建樹,再中序遍歷之
表達(dá)式樹確實(shí)是這樣的,中序遍歷也沒錯(cuò),不過要變成正常的表達(dá)式仍然是不夠的,還需要考慮優(yōu)先級(jí)去加括號(hào),偷懶方法當(dāng)然是全部加上括號(hào),這兒不寫了.
然后寫一下多叉樹的實(shí)現(xiàn)吧,這兒寫習(xí)慣了就給node外面加了一層包裝類,這樣添加的時(shí)候還是比較麻煩的,待優(yōu)化吧.
散列
散列也叫哈希,會(huì)遇到散列沖突問題,解決沖突最常用的是分離鏈接法,簡單來說就是將散列到同一個(gè)值的所有元素都插入到一個(gè)鏈表中去,來實(shí)現(xiàn)吧.
package com.fredal.structure;import java.util.LinkedList; import java.util.List;public class MyHashTable<T> {private static final int DEFAULT_SIZE=100;private int size;private List<T>[] lists;public MyHashTable(int size){this.size=size;lists=new LinkedList[size];//初始化鏈表數(shù)組for (int i = 0; i < lists.length; i++) {lists[i]=new LinkedList<T>();}}public MyHashTable(){this(DEFAULT_SIZE);}private int myHash(T x){int hashVal=x.hashCode();hashVal%=lists.length;if(hashVal<0){hashVal+=lists.length;}return hashVal;}//是否包含 使用自帶的就好 ~public boolean contains(T x){List<T> list=lists[myHash(x)];return list.contains(x);}//插入方法public void insert(T x){List<T> list=lists[myHash(x)];if(!list.contains(x)){list.add(x);size++;}}//移除方法public void remove(T x){List<T> list=lists[myHash(x)];if(list.contains(x)){list.remove(x);size--;}} }這里并沒有考慮再散列,因?yàn)閳?chǎng)景不復(fù)雜,再散列以后再談.
還有一種散列表叫探測(cè)散列表,也以后再說...
堆
堆也叫優(yōu)先隊(duì)列,是允許至少下列兩種操作的數(shù)據(jù)結(jié)構(gòu),插入和刪除并返回最小值.插入(insert)相當(dāng)于enqueue(入隊(duì)),而刪除最小值(deleteMin)則等價(jià)于隊(duì)列運(yùn)算dequeue(出隊(duì)).
我們要講的叫二叉堆,除了是一顆完整二叉樹外還要保持其堆序性質(zhì).例如最小二叉堆即,最小元在根上,而任意節(jié)點(diǎn)都小于它的所有后裔.
我們通過代碼模擬二叉堆
堆的應(yīng)用有許多,堆排序是最重要的之一,我們?cè)诤竺鏁?huì)講到.
更多文章與相關(guān)下載請(qǐng)點(diǎn)擊(http://langgengxin.com/2016/01/29/Structure-2/)
轉(zhuǎn)載于:https://www.cnblogs.com/fredal/p/Structure_2.html
總結(jié)
- 上一篇: Apache 配置虚拟主机
- 下一篇: 2015-01-14