Method implementation method, function implementation method.

Method implementation method, function implementation method. Use an algorithm.

1. What is an algorithm: an implementation method of a method, a procedural solution to a problem.

5 characteristics of the algorithm:

Input: 0 or more inputs.

Output: 1 or more outputs.

Finiteness: The method must execute in finite time.

Deterministic: Each statement of the method has a precise meaning and cannot be ambiguous. Must be the same input, have the same output.

Feasibility: Every sentence of the method can be executed by a computer.

 --

 

2. Algorithm mode:

Recursive: call itself by itself. The implementation must have an end condition.

Induction: tail recursion.

For example: selection sort
Sort the arrays a1...an.
the value of the i-bit
fun(0)
fun(i){
    if(i<n){
	    k=i;//k stores the subscript of the minimum value.
		for(j=i;j<n;j++){
			if(a[k]>a[j]){
				k=j;
			}
		}
		a[i] swaps positions with a[j];
		fun(i+1);
	}
}

 

Divide and conquer: Divide a large scale into small scales to solve separately, and then combine them together.

binary search
in array a1. . . an is sorted from small to large to find k.
fun(low,high,k,a){
	mid=(low+high)/2; //Round down.
	if(k==a[mid]) {
	    return mid;
	}else if(k<a[mid]){
		return fun(low,mid-1,k);
	}else{
	    return fun(mid+1,high,k);
	}
}

 

Dynamic programming: intermediate process values ​​are cached and used during the solution process of this problem.

Find the length of the longest common substring of strings A and B.
L[i,j]
A or B has a string of length 0: L[i,j]=0;
ai is the last of A, bj is the last of B, ai=bj: L[i,j]=L[i-1,j-1]+1;
ai! = bj: L [i, j] = min {L [i-1, j], L [i, j-1]};

//n is the length of A, m is the length of B.
fun(A,B){
	for(i=0;i<n:i++){
		L[i,0]=0;
	}
	for(j=0;j<m;j++){
		L[0,j]=0;
	}
	
	for(i=0;i<n;i++){
		for(j=0;j<m;j++){
			if(ai=bj){
			    return L[i-1,j-1]+1;//return fun(A.sub(i),B.sub(j));
			}else{
			    return min {L [i-1, j], L [i, j-1]}
			}
		}
	}
	
	return L[n,m];
}

 --

 

3. Method performance estimation method:

Performance is the usage of resources: time (time complexity), memory (space complexity), other resources.

High performance is: less time, less memory, less other resources.

Time estimation method:

Common time complexity comparison:

Ο (n!)> Ο (2 的 n 次方)> Ο (n2)> Ο (nlog2n)> Ο (n)> Ο (log2n)> Ο (1)

1. The number of executions of the basic steps. (Sometimes it is the sum of several basic steps) (Generally, the degree is a function of the scale n, and finding the item that increases the number the fastest in the formula is the time complexity of this algorithm)

The following analysis is to find the worst-case time complexity. 

 

Inductive: Selection Sort: Time Complexity:

The basic steps are: a[k]>a[j]

n=1:a[k]>a[j] execute 1 time

n=n:a[k]>a[j] The number of comparisons performed is c(n)=c(n-1)+(n-1) times

The formula expands to get:

c(n)=n(n-1)/2=1/2n squared-1/2n;

So the time complexity is O(square of n), read O n squared.

 

Divide and conquer: Binary search: Time complexity:

The basic steps are: one of each of the three comparisons is compared.

n=1:1

n>=2:c(n)=1+c(n/2 rounded down)

The formula expands:

c(n)<logn(round down)+1

So the time complexity is O(logn)

 

Dynamic programming: Find the length of the longest common substring of strings A and B: Time complexity:

The basic steps are: each time return L[i-1,j-1]+1 or return min{L[i-1,j],L[i,j-1]} will execute one.

When n,m: the number of executions is c(n,m)=n*m

So the time complexity is O(nm)

 

2.具体执行时间测量。例如:可以在函数开始时打个时间戳,结束时打个时间戳,求执行时间。

 

内存方面的估算方法:

1.基本步奏需要的辅助内存。

--

 

4.方法的可读性:

1.程序书写要规范,注意缩进、空行。

2.需要必要的合理的注释。函数功能注释,关键步奏注释。

3.起有自身功能描述的函数名,或变量名。

4.方法功能单一,低耦合,高内聚。

5.其他面向对象设计原则。

---------------------------------------------------------------------------------------------------------------

1.排序

1.选择排序:每次选出最小值放到最首位,然后规模减1再次选出最小值,直到规模为0。

 

    void fun(int[] a, int len) {
        for (int i = 0; i < len; i++) {
            int minIndex = i;
            for (int j = i; j < len; j++) {
                if (a[minIndex] > a[j]) {
                    minIndex = j;
                }
            }

            if (minIndex != i) {
                int temp = a[i];
                a[i] = a[minIndex];
                a[minIndex] = temp;
            }
        }
    }
    //时间复杂度是:O(n的平方)
 

 

--

2.交换排序

1.冒泡排序:相邻两项比较,值大的放后位,然后位置+1再重复前面的步骤,一直到位置为length结束(这样达到了最大值在最后面)。规模-1再次前面的步骤,直到规模为0.

 

    void fun(int[] a) {
        for (int i = 0; i < a.length; i++) {
            for (int j = 0; j < a.length-i-1; j++) {
                if (a[j] > a[j+1]) {
                    int temp = a[j];
                    a[j] = a[j+1];
                    a[j+1] = temp;
                }
            }
        }
    }

//Time complexity is: O(n squared)
 2. Quick sort: select a pivot value, place the small pivot value on the left, and place the large pivot value on the right. It is divided into two parts with the axis position as the boundary, and this process is recursive.
void quicksort(int[] v, int left, int right) {
    if (left < right) {

        int pivotValue = v[left];
        int low = left;
        int high = right;
        while (low < high) {
            
            //Starting from high, find the value smaller than the axis value and put it in the position of low
            // The value of the low position does not need to be saved, the value has been given to pivotValue, (or the high position, the first time of a non-loop))
            while (low < high && v[high] > pivotValue) {
                high--;
            }
            v[low] = v[high];
            
            //Reverse from low to find the one larger than the axis value and put it in the high position
            // (high位置的值不需要保存,值已经给low的位置)
            while (low < high && v[low] < pivotValue) {
                low++;
            }
            v[high] = v[low];
        }
        //现在low为轴心位置。
        v[low] = pivotValue;
        
        //以轴心位置分割两部分递归此过程。
        quicksort(v, left, low - 1);
        quicksort(v, low + 1, right);
    }
}
    
//时间复杂度是O(nlogn)

--

3.插入排序:i前的是有序的,把第i位的值插入到i前面的数组中。然后移动i的值,重复前面过程,直到i为数组长度。

 

public void insertSort(int a[]) {
    for (int i = 1; i < a.length; i++) {
        int insertIndex = i;
        int key = a[i];//当前要进行插入的值

        for (int j = i - 1; j >= 0; j--) {
            if (key < a[j]) {
                //后移元素
                a[j + 1] = a[j];
                insertIndex = j;
            } else {
                //大时在insertIndex的位置插入key
                break;
            }
        }
        a[insertIndex] = key;
    }
}

//时间复杂度是:O(n的平方)
 

 

--------------------------------------

2.查找

1.二分查找

 

int binary_search(int* a, int len, int goal)
{
    int low = 0;
    int high = len -1;
    while (low <= high)
    {
        int middle = (high - low) / 2 ;
        if (a[middle] == goal){
            return middle;
		}else if (a[middle] > goal){
            high = middle - 1;
		}else{
            low = middle + 1;
		}
    }
    return -1;
}
时间复杂度是:o(logn)

-------------------------------------

3.链表的逆序,插入,删除。

1.逆序:从头开始每个都提到最前面,q指向heap,p指向head的下一位。循环内先用q指向p的下一位,把p往前翻到head前,head再指向p。p向前移位。重复前面的步骤

Node reverse_Link(Node head) {
    Node p;
    Node q;
    q = head;
    p = head.next;
    while (p != null) {
        q.next = p.next;
        p.next = head;
        head = p;
        p = q.next;
    }
    return head;
}

 

 

2.插入:找到要插入的位置p,e.next=p.next,p.next=e;

//i位置前插入值e
insert_Link(Node head, int i, Node e) {
    Node p;
    p = head;

    for (int j = 1; j < i-1; j++) {
        if (p == null) {
            return;
        }
        p = p.next;
    }

    e.next = p.next;
    p.next = e;
}

 

 

3.删除:找到要删除的位置p,要删除的前一个位置p。q.next=p.next;

//删除位置i
delete_Link(Node head, int i){
    Node p;
    q = head;
    p = head;
    for (int j = 1; j < i; j++) {
        if (p == null) {
            return;
        }
        q = p;
        p = p.next;
    }

    if (p == null) {
        return;
    }

    if (p == q) {
        head = null;
    }

    q.next = p.next;
}

 

 

-------------------------------------

4.二叉树遍历与二叉树深度

二叉树遍历:

 

二叉树遍历:
前序遍历 根左右
void preOrder(BinaryTree bt) {
    if (pRoot != NULL) {
        visit(bt);//visit只是代表处理,关键的是结构
        preOrder(bt.leftChild);
        preOrder(bt.rightChild);
    }
}

中序遍历 左根右
void inOrder(BinaryTree bt) {
    if (pRoot != NULL) {
        inOrder(bt.leftChild);
        visit(bt); //visit只是代表处理,关键的是结构
        inOrder(bt.rightChild);
    }
}

后序遍历,左右根
void postOrder(BinaryTree bt) {
    if (bt != null) {
        postOrder (bt.leftChild);
        postOrder(bt.rightChild);
        visit(bt);//visit just represents the processing, the key is the structure
    }
}
  Binary tree depth  
int treeDeep(BinaryTree bt) {
    int deep = 0;
    if (bt == null) {
        return 0;
    } else {
        int lChilddeep = treeDeep(bt.lChild);
        int rChilddeep = treeDeep(bt.rChild);
        deep = lChilddeep >= rChilddeep ? lChilddeep + 1 : rChilddeep + 1;
    }
    return deep;
}
 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326759080&siteId=291194637