循环链表的插入删除

参考:https://www.cnblogs.com/lixiaolun/p/4643911.html

1、循环链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package circularList;

public class CircularLinkList {

Node head;//头节点

//初始化
public void init() {
head=new Node();
head.data=null;
head.next=null;
}

//插入
public void insert(String e) {
//如果是第一次插入
Node node=new Node();
node.data=e;

if(head.next==null) {
head.next=node;
node.next=head;
}else {
Node temp=head;
while(temp.next!=head) {
temp=temp.next;
}

temp.next=node;
node.next=head;
}
}

//删除
public void delete(String e) {
Node temp=head;

while(temp.next!=head)
{
//判断temp当前指向的结点的下一个结点是否是要删除的结点
if(temp.next.data.equals(e))
{
temp.next=temp.next.next;//删除结点
}else
{
temp=temp.next;//temp“指针”后移
}

}

}

public void printNode() {
Node node=head;

while(node.next!=head) {
node=node.next;
System.out.println(node.data);
}
}

class Node{
String data;
Node next;
}
}

2、测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package circularList;

public class TestCircularList {

public static void main(String[] args) {
// TODO Auto-generated method stub

CircularLinkList list=new CircularLinkList();
list.init();
list.insert("ct");
list.insert("ad");
list.insert("oo");
//list.delete("ad");

list.printNode();
}

}

快速排序

1、快速排序

快速排序的基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

2、时间复杂度

最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(nlogn) 

3、动态演示

Image text

4、算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package sort;

public class QuickSort {

public static void main(String[] args) {
// TODO Auto-generated method stub
int [] a= {1,2,7,4,3,2};
quickSort(a,0,a.length-1);
printArr(a);
}

public static void quickSort(int [] a,int left,int right) {
if(left>right) {
return;
}

int key=a[left];

int low=left;
int high=right;

while(low!=high) {
//从右往左找
while(a[high]>key && low<high) {
high=high-1;
}

//从左往右找
while(a[low]<key && low<high) {
low=low+1;
}

//如果low和high没有相遇,则交换
if(low<high) {
int temp=a[low];
a[low]=a[high];
a[high]=temp;
}
}

//key值归位
a[left]=a[low];
a[low]=key;

//递归调用子数组
quickSort(a,left,low-1);
quickSort(a,low+1,right);
}

public static void printArr(int [] a) {
for(int i=0;i<a.length;i++) {
System.out.println(a[i]);
}
}

}

归并排序

1、归并排序

1、和选择排序一样,归并排序的性能不受输入数据的影响,但表现比选择排序好的多,因为始终都是O(n log n)的时间复杂度。代价是需要额外的内存空间。

2、归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。归并排序是一种稳定的排序方法。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并

2、时间复杂度

最佳情况:T(n) = O(n) 最差情况:T(n) = O(nlogn) 平均情况:T(n) = O(nlogn)

3、动态演示

Image text

4、算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package sort;

import java.util.Arrays;

public class MergeSort {

public static void main(String[] args) {
// TODO Auto-generated method stub
// TODO Auto-generated method stub
int [] a= {99,45,67,12,84,59,32};
int [] re=mergeSort(a);
printArr(re);
}

public static int [] mergeSort(int [] a) {
if(a.length<2) {
return a;
}

int mid=a.length/2;

int [] left=Arrays.copyOfRange(a,0, mid);
int [] right=Arrays.copyOfRange(a,mid, a.length);
return merge(mergeSort(left),mergeSort(right));
}

public static int [] merge(int [] left,int [] right) {
int [] re=new int[left.length+right.length];

for(int index=0,i=0,j=0;index<re.length;index++) {
if(i>=left.length) {
re[index]=right[j];
j=j+1;
}else if(j>=right.length) {
re[index]=left[i];
i=i+1;
}else if(left[i]>right[j]) {
re[index]=right[j];
j=j+1;
}else if(left[i]<right[j]) {
re[index]=left[i];
i=i+1;
}
}

return re;
}

public static void printArr(int [] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
}
}

希尔排序

1、希尔排序

1、希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序,
同时该算法是冲破O(n^2)的第一批算法之一。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。

2、希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

2、时间复杂度

最佳情况:T(n) = O(nlog2 n) 最坏情况:T(n) = O(nlog2 n) 平均情况:T(n) =O(nlog2n) 

3、动态演示

Image text

4、算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package sort;

public class ShellSort {

public static void main(String[] args) {
// TODO Auto-generated method stub
int [] a= {99,45,67,12,84,59,32};
shellSort(a);
printArr(a);
}

public static void shellSort(int [] a) {
int cur;//记录即将插入的当前值
int dk=a.length/2;//增量

while(dk>0) {
for(int i=dk;i<a.length;i++) {//比较a.length-1趟
int index=i-dk;//记录有序数组的最后一位坐标
cur=a[i];

while(index>=0 && cur<a[index]) {//当前值小于有序数组中的值时
a[index+dk]=a[index];//记录后移
index=index-dk;
}

//当前值不小于前一个值时,把当前值赋给index+dk
a[index+dk]=cur;
}

dk=dk/2;
}
}

public static void printArr(int [] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
}

}

堆排序

1、堆排序

1堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

2、时间复杂度

最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(nlogn) 平均情况:T(n) = O(nlogn)

3、动态演示

Image text
Image text

4、算法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package sort;

public class HeapSort {

public static void main(String[] args) {
// TODO Auto-generated method stub
int [] a= {99,45,67,12,84,59,32};
heapSort(a);
printArr(a);
}

//堆排序
public static void heapSort(int[] a) {
int len=a.length;
if(len<1) {
return;
}
//构造一个最大堆
bulidMaxHeap(a);

//循环将最大值与最末位交换,再调整成最大堆
while(len>0) {
swap(a,0,len-1);
len--;
adjustHeap(a,0);
}

}

//建立初始大顶堆
public static void bulidMaxHeap(int[] a) {
//从最后一个非叶子节点开始
for(int i=(a.length-1)/2;i>=0;i--) {
adjustHeap(a,i);
}
}

//调整堆
public static void adjustHeap(int[] a,int i) {
int max=i;//记录最大值的下标

//如果有左孩子,比较是否大于左孩子
if(2*i<a.length && a[2*i]>a[max]) {
max=2*i;
}

//如果有右孩子,比较大小
if(2*i+1<a.length && a[2*i+1]>a[max]) {
max=2*i+1;
}

//如果父节点不是最大值,则与最大值交换,并递归调整被交换的最大值的位置
if(max!=i) {
swap(a,max,i);
adjustHeap(a,max);
}
}

public static void swap(int[] a,int m,int n) {
int temp=a[m];
a[m]=a[n];
a[n]=temp;
}

public static void printArr(int [] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
}
}

单链表的插入删除

1、单链表的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package danlianbiao;

public class Linklist {

Node head;

//初始化
public void init() {
head=new Node();
head.data=null;
head.next=null;
}

//插入
public void insert(String e) {
//如果是第一次插入
Node node=new Node();
node.data=e;

if(head.next==null) {
head.next=node;
}else {
Node temp=head;
while(temp.next!=null) {
temp=temp.next;
}

temp.next=node;
}
}

//删除
public void delete(String e) {
Node temp=head;

while(temp.next!=null)
{
//判断temp当前指向的结点的下一个结点是否是要删除的结点
if(temp.next.data.equals(e))
{
temp.next=temp.next.next;//删除结点
}else
{
temp=temp.next;//temp“指针”后移
}

}

}

public void printNode() {
Node node=head;

while(node.next!=null) {
System.out.println(node.next.data);
node=node.next;
}
}

class Node{
String data;
Node next;
}

}

2、测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package danlianbiao;

public class TestLink {

public static void main(String[] args) {
Linklist link=new Linklist();
link.init();
link.insert("ct");
link.insert("ad");
link.insert("oo");
//link.delete("ad");

link.printNode();
}

}

3、参考链接:https://www.cnblogs.com/lixiaolun/p/4643886.html

双向循环链表的插入删除

参考:https://www.cnblogs.com/lixiaolun/p/4643931.html

1、实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package doubleList;

public class DoubleLinkList {

Node head;//头节点

public void init() {
head=new Node();
head.data=null;
head.prev=head;
head.next=head;
}

//插入
public void insert(String e) {
Node node=new Node();
node.data=e;
//第一次插入
if(head.prev==head) {
head.next=node;
head.prev=node;
node.prev=head;
node.next=head;

}else {
//末尾插入
Node temp=head;
while(temp.next!=head) {
temp=temp.next;
}

temp.next=node;
node.prev=temp;
node.next=head;
head.prev=node;
}
}

public void delete(String e) {
Node temp=head;

while(temp.next!=head) {
if(temp.next.data.equals(e)) {
temp.next=temp.next.next;
temp.next.prev=temp;
}
temp=temp.next;
}

}

public void printNode() {
Node node=head;

while(node.next!=head) {
node=node.next;
System.out.println(node.data);
}
}

class Node{
String data;
Node prev;
Node next;
}
}

2、测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package doubleList;

public class TestDoubleList {

public static void main(String[] args) {
// TODO Auto-generated method stub

DoubleLinkList list=new DoubleLinkList();
list.init();
list.insert("ct");
list.insert("ad");
list.insert("oo");
//list.delete("ad");

list.printNode();
}

}

冒泡排序


1、冒泡排序:冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

2、时间复杂度
最佳情况:T(n) = O(n) 最差情况:T(n) = O(n^2) 平均情况:T(n) = O(n^2)

3、演示图
Image text

4、实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package sort;

public class BubbleSort {

public static void main(String[] args) {
// TODO Auto-generated method stub
int [] a= {1,8,3,7,5};
bubbleSort(a);
printArr(a);
}

public static void bubbleSort(int [] a) {
boolean flag=false;//标记某一趟排序是否发生交换,若无交换,说明当前数组已是排序好的数组

for(int i=0;i<a.length-1;i++) {//比length-1趟
for(int j=1;j<a.length-i;j++) {//每趟排好一个元素(最大的元素沉到最底),下一趟少不必比较这个元素
if(a[j]<a[j-1]) {
flag=true;
int temp=a[j];
a[j]=a[j-1];
a[j-1]=temp;
}
}

if(!flag) {//没有发生交换则跳出循环
break;
}
//System.out.println(flag);
}
}

public static void printArr(int [] a) {
for(int i=0;i<a.length;i++) {
System.out.print(a[i]+" ");
}
}
}

数组的二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
package xianxingbiao;

public class BiSearch {
//数组的二分查找
public static void main(String[] args) {
// TODO Auto-generated method stub

int [] arr=new int[] {1,2,3,4,5,6,7,8,9};//数组必须有序

int high=arr.length-1;
int low=0;
int mid=(low+high)/2;
int ele=9;//查找元素
int tag=-1;//目标元素的位置

while(low<=high) {
if(ele==arr[mid]) {
tag=mid;
break;
}else if(ele<arr[mid]) {
high=mid-1;
mid=(low+high)/2;
}else {
low=mid+1;
mid=(low+high)/2;
}
}

System.out.println(tag);
}
}

注意:
1、二分查找只能对有序数组查找;
2、时间复杂度:O(log2(n));

SpringMVC

1、springMVC
spring结构:
Image text

SpringMVC是Spring的一个模块,是基于MVC的web框架
Image text
1)用户端向前端控制器(DispatcherServlet)发起request请求
2)前端控制器向处理器映射器(HandlerMapping)发出请求查找处理器(Handler)(可根据XML和注解进行查找)
3)处理器映射器返回一个执行链给前端控制器
4)前端控制器请求处理器适配器(HandlerAdapter)执行handler
5)处理器适配器执行handler处理器
6)handler处理器返回ModelAndView给处理器适配器(ModelAndView是springmvc框架的一个底层对象)
7)处理器适配器将ModelAndView返回给前端控制器
8)前端控制器请求视图解析器(ViewResolver)进行视图解析(根据逻辑视图名解析成真正的视图)
9)视图解析器将view返回给前端控制器
10)前端控制器请求视图(view)进行视图渲染(视图渲染将模型数据(在ModelAndView对象中)填充到request域)
11)前端控制器向用户响应结果

重要组件:
1)前端控制器(DispatcherServlet):接受请求,响应结果,相当于转发器,通过前端控制器来交互,减少其他组件之间的耦合度
2)处理器映射器(HandlerMapping):根据请求的url查找handler
3)处理器适配器(HandlerAdapter):按照特定的规则去执行handler
4)处理器(handler)
注意:编写handler时按照handlerAdapter的要求去做才能正确执行handler
5)视图解析器(ViewResolver):根据逻辑视图名解析成真正的视图(view)
6)视图(View):是一个接口,通过实现类来支持不同的view类型(jsp、pdf……)

例子: