算法--线性结构
Posted hyf-huangyongfei
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法--线性结构相关的知识,希望对你有一定的参考价值。
数据的存储结构:顺序存储(ArrayList)、链式存储(LinkList)。
数据的逻辑结构:集合结构、线性结构、树形结构、图形结构。
二、算法
算法:解决问题的方法。
算法的特性:输入、输出、有穷、确定性、可行性。
算法的基本要求:正确性、可读性、健壮性、时间复杂度、空间复杂度。
三、线性结构
1、数组
普通数组:类似Java基本类型数组
对象数组:类似ArrayList在对象里面定义一个数组类型的成员变量。
数组中的算法:线性查找和二分法查找。
//线性查找
public void queryByIndex(){
int[] arr = new int[]{2,3,4,6,5};
int target = 4;
int index = -1;
for(int i=0;i<arr.length;i++){
if(target == arr[i]){
index = i;
break;
}
}
System.out.println(index)
}
//二分法查找,前提是数组的内容是有序的
public void queryByMid(){
int[] arr = new int[]{2,3,4,5,6};
int target = 4;
int index = -1;
int begin = 0;
int end = arr.length - 1;
int mid;
while(true){
mid = (begin+end)/2
if(target == arr[mid]){
index = i;
break;
}else if(target > arr[mid]){
end = mid - 1;
}else{
begin = mid + 1;
}
//不加这行会死循环
if(begin >= end){
break;
}
}
System.out.println(index)
}
2、栈
特点:先入后出,可以使用数组对象模拟。
int elements = new int[0];
//数组越界空指针异常不考虑
public void push(int element){
int[] arr = new int[elements + 1];
int len = elements.length;
for(int i=0;i < len;i++){
arr[i] = elements[i];
}
arr[len] = element;
elements = arr;
}
//数组越界空指针异常不考虑
public int pop(){
int[] arr = new int[elements - 1];
int len = elements.length;
int value = elements[len -1];
for(int i=0;i < len -1;i++){
arr[i] = elements[i];
}
elements = arr;
return value;
}
3、队列
特点:先进先出,可以使用数组对象模拟。
int elements = new int[0];
//入队数组越界空指针异常不考虑
public void add(int element){
int[] arr = new int[elements + 1];
int len = elements.length;
for(int i=0;i < len;i++){
arr[i] = elements[i];
}
arr[len] = element;
elements = arr;
}
//出队数组越界空指针异常不考虑
public int poll(){
int[] arr = new int[elements - 1];
int len = elements.length;
int value = elements[0];
for(int i=0;i < len;i++){
arr[i] = elements[i+1];
}
elements = arr;
return value;
}
4、单向链表
特点:一个节点除存储数据以外,还需存储下一个节点的指向。
public class Node{
//节点数据
int data;
//java对象在内存中是地址,可以理解下个节点的地址
Node next;
public Node(int data){
this.data = data;
}
public Node append(Node node){
Node currentNode = this;
while(true){
Node nextNode = currentNode.next;
if(null == nextNode){
break;
}
currentNode = nextNode;
}
//当前节点是可变的,因为循环中重新赋值了
currentNode.next = node;
return this;
}
public Node next(){
return this.next;
}
public int getData(){
return this.data;
}
public boolean isLast(){
if(null == this.next){
return true;
}
return false;
}
//移除也只能移除当前节点的下个节点
public void removeNext(){
Node deleteNode = this.next;
Node newNext = deleteNode.next();
this.next = newNext;
}
//只能插入当前节点后面
public void inset(Node node){
Node next = this.next;
this.next = node;
node.next = next;
}
}
5、单项循环链表
特点:和单链表相比,尾节点的下个节点指向首节点,构成一个单向循环。
public class LoopNode{
//节点数据
int data;
//java对象在内存中是地址,可以理解下个节点的地址
Node next = this;
public LoopNode(int data){
this.data = data;
}
public Node next(){
return this.next;
}
public int getData(){
return this.data;
}
//移除也只能移除当前节点的下个节点
public void removeNext(){
Node deleteNode = this.next;
Node newNext = deleteNode.next();
this.next = newNext;
}
//只能插入当前节点后面
public void inset(Node node){
Node next = this.next;
this.next = node;
node.next = next;
}
}
6、双向循环链表
特点:由数据、前一个节点和下个节点做成
public class DoubleNode{
DoubleNode pre = this;
DoubleNode next = this;
int data;
public DoubleNode(int data){
this.data = data;
}
//往后增加节点
public void after(DoubleNode node){
//当前节点的下个节点
DoubleNode oldNext = this.next;
//新增的节点
this.next = node;
node.pre = this;
node.next = oldNetx;
oldNext.pre = node;
}
}
7、递归
特点:在一个方法或者函数内部调用该方法,记得留出口,不然会栈溢出(StackOverflowError)。
//斐波那契数列 1 1 2 3 5 8 ...
public static int test(int i){
if(1 == i || 2 == i){
return 1;
}
return test(i - 1) + test(i - 2);
}
//汉诺塔
/**
* 共n个盘子
* 开始位置
* 中间位置
* 目标位置
* 无论有多少盘子,都认为只有两个,上面的所有盘子和下面一个盘子。
*/
public static int test2(int n,char from,char in ,char to){
if(1 == n){
System.out.println("第1个盘子从" + from + "移动到 " + to)
}else{
//移动上面的盘子到中间位置
test2(n-1,from,to,in);
System.out.println("第"+n+"盘子从" + from + "移动到 " + to);
//把上面的所有盘子从中间位置移动到目标位置
test2(n-1,in,from,to);
}
}
以上是关于算法--线性结构的主要内容,如果未能解决你的问题,请参考以下文章
C/C++数据结构-完整代码数据结构的理论,线性表(动态数组,链表)(完整的算法代码-增删改查-代码解析+运行结果解析)