数据结构
物理结构
顺序储存结构
使用连续的内存单位依次存放数据元素,物理存储次序与他们的逻辑次序相同
实现
数组
链式储存结构
使用地址分散的储存单元储存数据,逻辑结构由附加信息指定
实现
使用指针表示数据的逻辑结构
逻辑结构
- 线性表
- 树
- 图
线性结构
具有线性关系的数据结构
特点
-
ai只有一个前驱和一个后继,a0没有前驱,an没有后继
-
可以根据序号确定数据元素在线性结构中的逻辑次序
实现
抽象抽象数据类型
ADT List<T>{
boolean isEmpty()
int size()
T get(int i)
void set(int i,T x)
String toString()
int insert(T x,int i)
int insert(T x)
T remove(int i)
void clear()
int search(T x)
boolean contains(T key)
int insertDifferent(T x)
T remove(T x)
boolean equals(Object obj)
void addAll(List<T> lsit)
}
顺序储存结构
public class SeqList<T>{
protected Object[] element;
private int n;
public SeqList(int length){
if(length>=0){
this.element = new Object[length];
this.n = 0;
}else{
throw new IllegalArgumentsException("表长不能未负");
}
}
public SeqList(){
this(64);
}
public SeqList(T[] values){
this(values.length);
for(int i=0;i<values.length;i++){
this.element[i] = values[i];
}
this.n = values.length;
}
public boolean isEmpty(){
return this.n==0;
}
public int size(){
return this.n;
}
public T get(int i){
if(i>=0){
return this.element[i];
}else{
throw new IllegalArgumentsException("下标不能为负");
}
}
public void set(int i,T x){
this.element[i] = x;
}
public String toString(){
}
}
数组
储存相同类型数据元素的集合
储存空间连续
无法进行插入、删除操作
复杂度
空间:O(n)
时间:O(n)
链式储存结构
public Node<T>{
public T date;
public Node<T> next;
public Node(T data,Node<T> next){
this.data = data;
this.next = next;
}
public Node(){
this(null,null);
}
public String toString(){
return this.data.toString();
}
}
串
栈和队列
栈
只允许在一段进行插入和删除操作的线性表
栈顶:允许操作
栈底:不允许操作
特点:
后进先出(LIFO)
实现
public interface Stack<T>{
public abstract boolean isEmpty();
public abstract void push(T x);
public abstract T peek();
public abstract T pop();
}
顺序储存结构
public final class SeqStack<T>{
private SeqList<T> list;
public SeqStack(int length){
this.list = new Seqlist<T>(length);
}
public SeqStack(){
this(64);
}
public boolean isEmpty(){
return this.list.isEmpty();
}
public void push(T x){
this.list.insert(x);
}
public T peek(){
return this.list.get(this.list.size()-1);
}
public T pop(){
return this.list.remove(this.list.size()-1);
}
}
链式储存结构
public final class LinkedStack<T> impelements Stack<T>{
private SinglyList<T> list;
public LinkedStack(){
this.list = new SinglyList<T>();
}
public boolean isEmpty(){
return this.list.isEmpty();
}
public void push(T x){
this.list.insert(0,x);
}
public T peek(){
return this.list.get(0);
}
public T pop(){
return this.list.remove(0);
}
}
应用
- 嵌套调用的实现基础
- 以非递归方式实现递归算法
队列
删除,插入分别在两端的线性表
特点:
先进先出(FIFO)
实现
public interface Queue<T>{
public abstract boolean isEmpty();
public abstract boolean add(T x);
public abstract T peek();
public abstract T poll();
}
顺序储存结构
public final class SeqQueue<T> implements Queue<T>{
private Object element[];
private int front,rear;
public SeqQuene(int length){
if(length<64){
length = 64;
}
this.element = new Object[length];
this.front = this.rear = 0;
}
public SeqQueue(){
this(64);
}
public boolean isEmpty(){
return this.front = this.rear;
}
public boolean add(T x){
if(x==null){
return false;
}
if(this.front==(this.rear+1)%this.element.length){
Object[] temp = this.element;
this.element = new Object[temp*2];
int j = 0;
for(int i=this.front;i!=this.rear;i=(i+1)%temp.length){
this.element[j++] = temp[i];
}
this.front = 0;
this.rear= j;
}
this.element[this.rear] = x;
this.rear = (this.rear+1)%this.element.length;
return true;
}
public T peek(){
reutnr this.isEmpty()?null:(T)this.element[this.front];
}
public T poll(){
if(this.isEmpty()){
return null;
}
T temp = (T)this.element[this.front];
this.front = (this.rear+1)%this.element.length;
return temp;
}
}
数组和广义表
图
由顶点集合及顶点间及顶点间关系集合组成的一种数据结构
无向图
没有方向,边用无序对表示
有向图
边有方向,每条边用有序对表示
完全图
边的数量达到最大值
无向图
n*(n-1)/2
有向图
n*(n-1)
带权图
边具有权值
也成为网络
邻接顶点
一条边中的两个顶点
度
-
度为零称为孤立点
-
度为一称为悬挂点
在有向图中有入度和出度的区别
度为入度加出度
无向图边数等于所有顶点度的和的二分之一
有向图所有顶点的入度之和等于出度之和等于边数
子图
顶点和边为子集
当顶点相同时,为生成子图
连通性
一个顶点到另一顶点有路径则连通
图任意一个顶点到另一顶点连通则图连通
非连通图的极大连通子图为一个连通分量
当任意一个顶点到另一顶点连通且存在一条返回的路径则为强连通
路径
实现
矩阵类
public class Matrix {
private int rows,columns;
private int[][] elements;
public Matrix(int m,int n) {
this.elements = new int[m][n];
this.rows = m;
this.columns = n;
}
public Matrix(int m,int n,int[][] value) {
this.elements = new int[m][n];
this.rows = m;
this.columns = n;
for(int i=0; i<value.length&&i<m; i++) {
for(int j=0; j<value[i].length&&j<n; j++) {
this.elements[i][j] = value[i][j];
}
}
}
public Matrix(int n) {
this(n,n);
}
public int getRows() {
return this.rows;
}
public int getColumns() {
return this.columns;
}
public int get(int m,int n) {
if(m>=0&&m<rows&&n>=0&&n<columns) {
return this.elements[m][n];
}
throw new IndexOutOfBoundsException("超出矩阵行数或列数");
}
public void set(int m, int n, int x) {
if(m>=0&&m<rows&&n>=0&&n<columns) {
this.elements[m][n] = x;
}
else throw new IndexOutOfBoundsException();
}
public String toString() {
String str = " 矩阵" + this.getClass().getName()+"("+this.rows+" * "+this.columns+"): \n";
for(int i=0;i<this.rows;i++) {
for(int j=0;j<this.columns;j++) {
str+=String.format("%6d", this.elements[i][j]);
}
str += "\n";
}
return str;
}
public void setRowsColumns(int m,int n) {
}
public boolean equals(Matrix mat) {
if(elements.length!=mat.rows||elements[0].length!=mat.columns) {
return false;
}
else {
for(int i=0; i<elements.length; i++) {
for(int j=0; j<elements[0].length; j++) {
if(elements[i][j]!=mat.elements[i][j]) {
return false;
}
}
}
return true;
}
}
public boolean isSymmetric() {
int i = 1,j = 0;
if(elements.length!=elements[0].length) {
return false;
}
for(;i<elements.length;i++) {
for(;j<i;j++) {
if(elements[i][j]!=elements[j][i]) {
return false;
}
}
}
return true;
}
邻接矩阵
顺序储存结构
使用线性表储存
//顶点类,线性表储存顶点
public abstract class AbstractGraph<T>{
protected static final int MAX_WEIGHT = 0x0000ffff;
protected SeqList<T> vertexlist;
public AbstractGraph(int length){
this.vertexlist = new SeqList<T>(length);
}
public AbstractGraph(){
this(10);
}
public int vertexCount(){
return this.vertexlist.size();
}
public String toString(){
return "顶点集合:"+ this.vertexlist.toString()+"\n";
}
public void setVertex(int i, T x){
this.vertexlist.set(i,x);
}
public abstract int insertVertex();
public abstract void removeVertex();
public abstract int weight(int i,int j);
public abstract int next(int i,int j);
}
//边类
//图(起点序号,终点序号,权值)
public class Triple implements Comparable<Triple>, Addible<Triple> {
public int row,column,value;
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getColumn() {
return column;
}
public void setColumn(int column) {
this.column = column;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public Triple(int row,int column,int value) {
if(row>=0&&column>=0) {
this.row = row;
this.column = column;
this.value = value;
}
else throw new IllegalArgumentException("");
}
public Triple(Triple tri) {
this(tri.row, tri.column, tri.value);
}
public Triple() {
this(0,0,0);
}
@Override
public void add(Triple tri) {
if(this.compareTo(tri)==0) {
this.value += tri.value;
}else {
throw new IllegalArgumentException();
}
}
public String toString() {
return "("+row+","+column+","+value+")";
}
@Override
public boolean removable() {
return this.value==0;
}
@Override
public int compareTo(Triple o) {
// TODO Auto-generated method stub
if(this.row<o.row) {
return -1;
}else if(this.row==o.row&&this.column==o.column){
return 0;
}else if(this.row==o.row&&this.column==o.column) {
return -1;
}else {
return 1;
}
}
public boolean equals(Triple tri) {
if(this.row==tri.row&&this.column==tri.column&&this.value==tri.value) return true;
else return false;
}
public Triple toSymmetry() {
return new Triple(this.column,this.row,this.value);
}
}
public class MatrixGraph<T> extends AbatractGraph<T>{
private SeqList<T> vertexlist;
private Matrix adjaMatrix;
public int vertexCount() {
return this.vertexlist.size();
}
public int weight(int i, int j) {
return this.adjaMatrix.get(i, j);
}
public T getVertex(int i) {
return this.vertexlist.get(i);
}
public MatrixGraph(SeqList<T> vertexlist, Matrix adjaMatrix) { if(vertexlist.size()!=adjaMatrix.getRows()||vertexlist.size()!=adjaMatrix.getColumns()) {
throw new IndexOutOfBoundsException("");
}
this.vertexlist = vertexlist;
this.adjaMatrix = adjaMatrix;
}
public MatrixGraph() {
vertexlist = new SeqList<T>(10);
adjaMatrix = new Matrix(10);
}
}
边
-
插入
-
public void insertEdge(int i,int j,int weight){ if(!j=i){ if(weight<=0||weight>MAX_WEIGHT){ //当不成环且权值有效时 weight = MAX_WEIGHT; } this.matrix.set(i,j,weight); //设置矩阵权值表示边 }else throw new IllegalArgunmentException("不能成环"); public void insertEdge(Triple edge){ this.insertEdge(edge.row,edge.column,edge.value);//用边类的三元组设置边 } }
-
-
删除
-
public void removeEdge(int i,int j){ if(i!=j) this.matrix.set(i,j,MAX_WEIGHT); } public void removeEdge(Triple edge){ this.removeEdge(edge.row,edge.column); }
-
顶点
-
插入
-
public int insertVertex(T x){ int i = this.vertexlist.size(x); if(i>=this.matrix.getRow()){ this.matrix.setRowColumns(i+1,i+1); } for(int j=0;j<i;j++){ this.matrix.set(i,j,MAX_WEIGHT); this.matrix.set(j,i,MAX_WEIGHT); } return i; }
-
-
删除
-
public void removeVertex(int i){ int n = this.vertexCount(); if(i>=0&&i<n){ this.vertexlist.remove(i); for(int j=i+1;j<n;j++){ for(int k=0;k<n;k++){ this.matrix.set(j-1,k,this.matrix.get(j,k));//邻接矩阵少一行一列 } } this.matrix.setRowColumns(n-1,n-1); }else throw new IndexOutOfBoundsException("i = "+i); }
-
-
获得邻接顶点和边的权值
-
//获得权值 public int weight(int i,int j){ return this.matrix.get(i,j);//返回矩阵中的值 } protected int next(int i,int j){ int n = this.vertexlistCount(); if(i>=0&&i<n&&j>=-1&&j<n&&i!=j){ //检查是否成环,i在矩阵内,j符合条件 for(int k=j+1;k<n;k++){ if(this.matrix.get(i,k)!=0&&this.matrix.get(i,k)!=MAX_WEIGHT){ return k; } } } return -1; }
-
邻接表
实现
//链表储存矩阵实现
public class LinkedMatrix{
private int rows,columns;
SeqList<PolySinglyList<Triple>> rowlist;
public LinkedMatrix(int i,int n){
if(m>0&&n>0){
this.rows = m;
this.columns = n;
this.rowlist = new SeqList<PolySinglyList<Triple>>();
for(int i=0;i<m;i++){
this.rowlist.insert(new PolySinglyList<Triple>>());
}
}else throw new IllegalArgunmentException("矩阵行列数不能小于零");
}
public LinkedMatrix(int m){
this(m,m);
}
public LinkedMatrix(int m,int n,Triple[] tris){
this(m,n);
for(int i=0;i<this.length;i++){
this.set(tri[i]);
}
}
public int getRows()
public int getColumns()
}
public class AdjListGraph<T> extends AbstractGraph<T>{
protected LinkedMatrix adjlist;
public AdjListGtrph(int length){
super(length);
this.adjlist = new LinkedMatrix(length,length);
}
public AdjListGraph(){
this(10);
}
public AdjListGraph(T[] vertices){
this(vertices.length);
for(int i=0;i<vertices.length;i++){
this.insertVertex(vertices[i]);
}
}
public AdjListGraph(T[] vertexlist,Triple[] edges){
this(vertices); //用数组构建含有数组元素的顺序表
for(int i=0;i<edges.length;i++){
this.insertEdge(edges[i]);
}
}
public String toString(){
}
}
边
-
插入
-
public void insertEdge(int i,int j,int weight){ if(i!=j){ if(weight<=0||weight>=MAX_WEIGHT){ weight = 0; } this.adjlist.set(i,j,weight); }else throw new IllegalArgumentException("不可成环"); } public void insertEdge(Triple edge){ this.insertEdge(edge.getRow(),edge.getColumn(),edge.getValue()); }
-
-
删除
-
public void removeEdge(int i,int j){ if(i!=j){ this.adjlist.set(new Triple(i,j,MAX_WEIGHT)); } } public void removeEdge(Triple edge){ this.removeEdge(edge.getRow(),edge.getColumn(),edge.getValue()); }
-
顶点
-
插入
-
public int insertVertex(T x){ int i = this.vertexlist.insert(x); if(i>=this.adjalist.getRows()){ this.adjlist.setRowsColumns(i+1,j+1); } return i; }
-
-
删除
-
public void removeVertex(int i){ int n= this.vertexCount(); if(i>=0&&i<n){ SortedSinglyList<Triple> link = this.adjlist.rowlist.get(i); for(Node<Triple> p=link.head.next;p!=null;p=p.next){ this.removeEdge(p.data.toSymmetry()); } n--; this.adjlist.remove(i); this.adjlist.setRowsColumns(n,n); for(int j=0;j<n;j++){ link = this.adjlist.rowlist.get(j); for(Node<Triple> p=link;p!=null;p=p.next){ if(p.data.row>i){ p.data.row--; } if(p.data.column>i){ p.data.column--; } } } this.vertexlist.remove(i); }else throw new IndexOutOfBoundsException(""); }
-
-
获得邻接顶点获得邻接顶点和边的权值
-
public int weight(int i,int j){ if(i==j){ return 0; } int weight = this.adjlist.get(i,j); return weight!=0?weight:MAX_WEIGHT; } protected int next(int i,int j){ int n= this.vertexCount(); if(i>=0&&i<n&&j>=-1&&j<n&&i!=j){ SortedSinglyList<Triple> link = new this.adjlist.rowlist.get(i); Node<Triple> find = link.head.next; if(j==-1){ return find!=null?find.data.column:-1; } find = link.search(new Triple(i,j,0)); if(find!=null){ find = find.next; if(find!=null){ return find.data.column; } } } return -1; }
-
遍历
深度优先搜索
public void DFSTraverse(int i){
boolean visited = new boolean[this.vertexCount()];
int j = i;
do{
if(!visited[j]){
System.out.print("{");
this.depthfs(j,visited);
System.out.print("}");
}
j = (j+1)%this.vertexCount(); //使j从1到vertexCOunt()再回到0
}while(j!=i)
System.out.println();
}
private void depthfs(int i,boolean[] visited){
System.out.println(this.getVertex(i)+"");
visited[i] =true;
int j=this.next(i,-1);
while(j!=i){
if(!visited[j]){
depthfs(j,visited); //递归访问该顶点的邻接顶点
}
j = this.next(i,j);
}
}
广度优先搜索
public void BFSTraverse(int i) {
boolean[] visited = new boolean[this.vertexCount()];
int j = i;
do {
if(!visited[j]) {
System.out.print("{");
breadthfs(j,visited);
System.out.print("}");
}
j = (j+1)%this.vertexCount();
}while(j!=i);
System.out.println();
}
private void breadthfs(int i, boolean[] visited) {
System.out.print(vertexlist.get(i)+"");
visited[i] = true;
SeqQuene<Integer> que = new SeqQuene<Integer>();
que.add(i);
while(!que.isEmpty()) {
i = que.poll();
for(int j=0;j<adjaMatrix.getColumns();j++) {
if(adjaMatrix.get(i,j)!=0&&adjaMatrix.get(i, j)!=Integer.MAX_VALUE&&!visited[j]) {
System.out.print(vertexlist.get(i)+" ");
visited[j] = true;
que.add(j);
}
}
}
}
最小生成树
prim算法
/*
讲已选择的顶点作为一个集合,选择对于这个集合来说权值最小的边进行连接将结点添加进集合
*/
public void minSpanTree() {
Triple[] mst= new Triple[vertexCount()-1];
for (int i=0; i<mst.length;i++) {
mst[i] = new Triple(0,i+1,this.weight(0,i+1));
}
for (int i=0;i<mst.length;i++) {
int minweight = mst[i].value, min=i;
for (int j=i+1;j<mst.length;j++) {
if(mst[j].value<minweight) {
minweight=mst[j].value;
min = j;
}
}
Triple edge = mst[min];
mst[min]=mst[i];
mst[i] = edge;
int tv=edge.column;
for(int j=i+1;j<mst.length;j++) {
int v=mst[j].column;
int weight=this.weight(tv,v);
if(weight<mst[j].value){
mst[j]=new Triple(tv, v, weight);
}
}
}
System.out.print("\n最小生成树的边集合:");
int mincost=0;
for (int i=0; i<mst.length; i++) {
System.out. print(mst[i]+"");
mincost += mst[i].value;
System.out.println(", 最小代价为:"+mincost);
}
}
Kruskal算法
import java.until.Comparator
public class MinSpanTree{
private Triple[] mst;
private int cost = 0;
public MinSpanTree(int n,Triple[] edge,Comparator<Triple> empr){
this.mst = new Triple[n-1];
Heap<Triple> minheap = new Heap<Triple>(true,edges,empr);
UnionFindSet ufset = new UnionFindSet(n);
System.out.println("并查集:"+ufset.toString()+"");
int i=0;
for(int j=0;j<n;j++){
Triple minedge = minheap.removeRoot();
System.out.print("最小边"+minedge.toString());
if(ufset.union(minedge.row,minedge.column)){
this.mst[i++]=minedge;
this.cost += minedge.value;
System.out.println("插入边:"+minedge.toString()+"");
}
}
}
public String toString();
private static void print(boolean table[])
}
最短路径
dijkstra算法
/*
前述数组S
dist数组
path数组
*/
floyd算法
树
树是由n个结点组成的有限集合。n=0的树称为空树
- 有一个特殊结点称为根结点,只有后继结点,没有前驱结点
- 除根结点之外的其他结点分为m个互不相交的集合T0、T1、……Tm-1也具有树结构,也就是根的子树
术语
父母、孩子、兄弟结点
- 一个结点子树的根节点称为其孩子
- 相对的该结点是其孩子结点的父母结点
- 拥有同一个父母结点的多个结点之间称为兄弟
度
结点拥有的子树的棵数
结点层次、树的高度
结点的层次是结点处于树中的层次位置,约定根结点的层次为1其他层次是其父母结点的层次加1
树的高度或深度是树中结点的最大层次数
边、路径、直径
连接两个结点的的有序对为边
从一个结点到另一个结点间的有序对集合
有序对数是路径长度
二叉树
性质
- 根结点层次为1,则二叉树第i层最多有2^(i-1)个结点(归纳法证明)
- 在高度为h的二叉树中,最多由2^h^-1个结点
- 叶子结点数为n
0,2度结点数为n2,则n0=n2+1 -
- 完全二叉树:具有2^h^-1个结点的二叉树
- 满二叉树:一颗具有n个结点高度为h的二叉树。如果它的每个结点都与高度为h的满二叉树中序号为0~n-1结点一一对应,则为完全二叉树
- 一个具有n个结点的完全二叉树,其高度h = ==[log
2n+]取整==+1(<h-1log2(n+1)=<h) - 一颗具有n个结点的完全二叉树,对序号为i的结点
- 若i=0,则i为根结点,无父母结点;i>0,则i的父母结点序号为==(i-1)/2== 取整
- 若2i+1<n,则i的左孩子结点序号为2i+1,否则i无左孩子
- 若2i+2<n,则i的右孩子结点序号为2i+2,否则i无右孩子
遍历
孩子优先
-
先根次序
访问根节点,遍历左子树,遍历右子树
-
中根次序
遍历左子树,访问根结点,遍历右子树
-
后根次序
遍历左子树,遍历右子树,访问根结点
兄弟优先
按层次进行访问,每层从左至右访问同层结点,访问完后进入下一结点
实现
ADT BinaryTree<T>{
boolean isEmpty()
int size()
int height()
void predrder()
void inorder()
void postorder()
void levelorder()
BinaryNode<T> insert(T x)
BinaryNode<T> insert(BinaryNode<T> p,boolean leftChild)
void remove(Binary<T> parent,boolean leftChild)
void clear()
BinaryNode<T> search(T key)
boolean contains(T key)
int level(T key)
}
顺序储存结构
顺序储存结构不能反映二叉树的数据关系
非完全二叉树不能采用顺序储存结构
链式储存结构
//结点类
public class BinaryNode<T>{
public T data;
public BinaryNode<T> left,right;
public BinaryNode(T data,BinaryNode<T> left,){
this.data = data;
this.left = left;
this.right = right;
}
public BinaryNode(T data){
this(data,null,null);
}
public String toString(){
return this.data.toString();
}
public boolean isLeaf(){
return this.left==null&&this.right==null;
}
}
//二叉树类
public Class BinaryTree<T>{
public BinaryNode<T> root;
public BinaryTree(){
this.root = null;
}
public boolean isEmpty(){
return this.root==null;
}
//插入结点
public BinaryNode<T> insert(T x){
return this.root = new BinaryNode<T>(x,this.root,null);
}
public BinaryNode<T> insert(BinaryNode<T> parent,T x,boolean leftChild){
if(x==null){
return null;
}
if(leftChild){
return parent.left = new BinaryNode<T>(x,parent,null);
}else{
return parent.right = new BinaryNode<T>(x,null,parent);
}
}
public void remove(BinaryNode<T> parent,boolean leftChild){
if(leftChild){
parent.left = null;
}else{
parent.right = null;
}
}
public void clear(){
this.root = null;
}
//先序遍历
public void proorder(){
preorder(this.root);
System.out.println();
}
private void preorder(BinaryNode<T> p){
if(p!=null){
System.out.print(p.data.toString()+"");
preorder(p.left);
preorder(p.right);
}
}
//
public String toString(){
return toString(this.root);
}
private String toString(BinaryNode<T> p){
if(p==null){
return "^";
}
return p.data.toString()+" "+toString(p.left)+" "+toString(p.right);
}
}
//构造二叉树
层次遍历
非递归先序遍历
线索二叉树
查找
平均查找长度ASL= 累加(pi*ci)
pi查找概率
ci查找次数
顺序查找
基于遍历算法,逐一比较
ASL成功
(n+1)/2
ASL不成功
n
二分法查找
- 顺序储存
- 数据元素排序
复杂度
log2n
索引表分块索引
散列
二叉排序树
平衡二叉树
排序
插入排序
直接插入
描述
将设置排序子序列和未排序子序列
开始时,序列全在未排序序列中,不断选择未排序序列中的元素,放入已排序序列中,最后元素全在已排序序列中
分析
设有n个元素,需要执行n-1次,每次比较次数和移动次数和初始排列有关
最好情况下,序列已经排序,比较次数为n-1,移动次数为(2n-1)时间复杂度为O(n)
最坏情况下,序列完全相反,第i次插入元素比较i次,移动i+2次,时间复杂度为O(n^2^)
稳定
实现
public class Array{
public static void insertSort(int[] key){
for(int i=0;i<key.length;i++){
int temp = key[i];
for(int j=0;j>=0&&temp<key[j];j++){
key[j+1] = key[j];
}
key[j+1] = temp;
}
}
}
希尔排序
描述
将序列内相隔一定距离(增量)的元素组成分组,进行直接排序
增量初值一般为序列长度一半,之后每次增量减半,最后为1
组内元素逐次增多并排序
分析
三层循环实现
最外层循环变化delta进行扫描
内两层实现直接插入
实现
public class shellSort(int[] keys){
for(int delta = keys.length/2;delta>0;delta/=2){
for(int i = delta;i<keys.length;i++){
int temp = key[i];
for(int j=i-delta;j>=0&&temp<key[j];j-=delta){
keys[j+delta] = key[j];
}
keys[j+delta] = temp;
}
}
}
交换排序
冒泡排序
描述
比较相邻的两个元素,如果反序就交换
分析
最好情况下,序列排序,只需要扫描一趟,时间复杂度O(n)
最坏情况下,序列反序,时间复杂度为O(n^2^)
实现
private static void swap(int[] keys,int i,int j){
int temp= key[j];
key[j] = key[i];
key[i] = temp;
}
public static void bubbkeSort(int[] keys){
bubbleSort(keys,true);
}
public static void bubbleSort(int[] keys,boolean asc){
boolean exchange = true;
for(int i=0;i<keys.length&&exchange;i++){
exchange = false;
for(int j=0;j<keys.length-i;j++){
if(asc?keys[j]>keys[j+1]:keys[j]<keys[j+1]){
swaq(keys,j,j+1);
exchange = true;
}
}
}
}
快速排序
描述
在序列中选择一个元素为基准值,每趟从序列的两端开始交换,将小于基准值得元素交换到序列前端,大于基准值得元素交换到序列后端
实现
public static void quickSort(int[] keys){
quickSort(keys,0,keys.length-1);
}
private static void quickSort(int[] keys,int begin,int end){
if(begin>=0&&begin<keys.length&&end>=0&&end<keys.length&&begin<end){
int i =begin,j=end;
int vot= keys[i];
while(i!=j){
while(i<j&&keys[i]>=vot){
j--;
}
if(i<j){
keys[i++] =keys[i];
}
while(i<j&&keys[i]<=vot){
i++;
}
if(i<j){
keys][j--] = keys[i];
}
keys[i] = vot;
quickSort(keys,beging,j-1);
quickSort(keys,i+1,end);
}
}
分析
最好情况下,每趟排序将序列分成相近得两个子序列,时间复杂度O(n*log2n)
最坏情况下,每趟将序列分成长度差异很大的两个子序列,时间复杂度O(n^2^)
选择排序
直接选择排序
描述
在n个元素中选择最小得元素放在最前位置
实现
public static void SelectSort(int[] keys){
for(int i=0;i<keys.length;i++){
int min = i;
for(int j= i+1;j<keys.length;j++){
if(keys[j]<keys[min]){
min = j;
}
if(min!=i){
swaq(keys,i,j);
}
}
}
}
分析
第i趟的比较次数为n-i次,移动次数与初始排序有关,时间复杂度为O(n^2^)
堆排序
描述
利用二叉树的结构,将序列用二叉树结构储存,并排序,形成最大/最小堆
实现
public static void heapSort(int[] keys){
heapSort(keys,true);
}
public static void heapSort(int[] keys,boolean minheap){
for(int i=keys.length/2;i>=0;i--){
sift(keys,i,keys.length-1,minheap);
}
for(int i=keys.length;i>0;i--){
swaq(keys,0,1);
sift(keys,0,i-1,minheap);
}
}
private static void sift(int[] keys,int parent,int end,boolean minheap){
int child = 2*parent+1;
int value = keys[parent];
while(child<=end){
if(child<end&&(minheap?keys[child]>keys[child+1]:keys[child]<keys[child+1])){
child++;
}
if(minheap?value>keys[child]:value<keys[child]){
keys[parent] = keys[child];
parent = child;
child = 2*parent+1;
}else{
break;
}
keys[parent] = value;
print(keys);
}
}
归并排序
描述
分而治之思想,将未排序序列分成若干组子序列对子序列进行排序,排序后合并
实现
private static void merge(int[] x,int[] y,int begin1,int begin2,int n){
int i = begin1,j = begin2,k = begin1;
while(i<begin1+n&&j<begin2+n&&j<x.length){
if(x[i]<x[j]){
y[k++] = x[i++];
}else{
y[k++] = x[j++];
}
while(j<begin1+n&&i<x.length){
y[k++] = x[i++];
}
while(j<begin2&&j<x.length){
y[k++] = x[j++];
}
}
}
private static void mergepass(int[] x,int[] y,int n){
for(int i=0;i<x.length;i+=2*n){
merge(x,y,i,i+n,n);
}
}
public static void mergeSort(int[] x){
int[] y = new int[x.length];
int n = 1;
while(n<x.length){
mergepass(x,y,n);
n*=2;
if(n<x.length){
mergepass(y,x,n);
n*=2;
}
}
}
分析
时间复杂度为O(n*log2n),空间复杂度为O(n)
归并排序稳定