1.数组
1.线性数据结构强调存储与顺序
2.有东西先把东西存起来
数组特点
数组定长
数组是定长的,我们以为的其实是js引擎帮我们扩容,内存是操作系统来分配的
尽量给自己的东西设置好数组长度
特性
1.存储在物理空间上(在磁盘上)是连续的。如果存储的到头了,就再去磁盘里找,有没有一个空间能存放的下它。
2.底层数组的长度不变。(就是你一开始设置了是多长,就是多长)
3.数组变量指向第一个元素的位置(数组下标)
数组优点
1.查询性能好(通过偏移查询)
数组缺点
1.空间必须是连续的,数组比较大,当系统的 空间碎片较多的时候,容易存不下。
2.因为数组的长度是固定的,所以数组的内容难以被添加和删除,添加和删除是很消耗性能的。
在js中创建一个数组
let a = [1,2,3]
let arr = new Array(10) //确定数组长度
2.链表
数组的存放是连续的,链表的存放是可以碎片的,用引用来把他们连起来。
链表特点
1.空间上不连续
2.每存放一个值都会有一个引用空间
优点
1.只要内存足够大,就能存的下,不用担心空间碎片的问题
2.链表的添加和删除非常容易
缺点
1.链表的查询速度慢
2.链表的每一个查询都需要创建一个next值(就是引用值),直接double了空间。但是可以通过增加数据量的存储来降低引用值大小(引用值大小没变,只是相对于数据量变小了)
延伸(重要):
1.想传递一个链表,必须传递链表的根节点
2.每一个链表的节点都可以认为自己是根节点
数组和链表
循环遍历方法
数组
// 遍历数组 经典for循环
let a = [1, 2, 3, 4, 5]
function travel(array) {
if (array == null) return; // 一定要做这个检验
for (let index = 0; index < array.length; index++) {
console.log(array[index]);
}
}
travel(a)
链表
function ode(value) {
this.value = value;
this.next = null;
}
let a = new ode(1);
let b = new ode(2);
let c = new ode(3);
let d = new ode(4);
a.next = b;
b.next = c;
c.next = d;
// 循环遍历 传递一个链表 传的是根节点
function travel(root) {
let temp = root;
while (true) {
if (temp == null) {
break;
} else {
console.log(temp.value);
}
temp=temp.next;
}
}
travel(a)
递归遍历方法
数组
let a = [1, 2, 3, 4, 5]
function travel(arr, i) {
if (arr == null || i >= arr.length) return;
console.log(arr[i], '递归遍历');
travel(arr, i + 1)
}
travel(a, 0)
链表
function ode(value) {
this.value = value;
this.next = null;
}
let a = new ode(1);
let b = new ode(2);
let c = new ode(3);
let d = new ode(4);
a.next = b;
b.next = c;
c.next = d;
function travel(root) {
if (root == null) return;
console.log(root.value, '递归算法');
travel(root.next) // 找到一直在循环做的事情
}
travel(a)
链表逆置
function ode(value) {
this.value = value;
this.next = null;
}
let a = new ode(1);
let b = new ode(2);
let c = new ode(3);
let d = new ode(4);
a.next = b;
b.next = c;
c.next = d;
function reverse(root) {
//定位到倒数第二个节点,
if (root.next.next == null) {
//把最后一个节点指向倒数第二个
root.next.next = root;
//退出节点
return root.next;
} else {
//递归
let result = reverse(root.next);
//让该节点的下一个节点指向自己
root.next.next = root;
//让该节点指向null
root.next = null;
return result;
}
}
//遍历一下
function travel(root) {
if (root == null) return;
console.log(root.value);
travel(root.next)
}
travel(reverse(a))
冒泡排序(比较、交换、排序)
- 算法步骤
- 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
- 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。
- 针对所有的元素重复以上的步骤,除了最后一个。
- 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
let arry = [4, 7, 2, 6, 0, 8, 9, 1, 3];
/**
- 比较
- 交换
- 排序
- */
function compare(a, b) {
if (a > b) return true;
else return false;
}
function exchange(arry, i, j) {
let temp = arry[j]
arry[j] = arry[i]
arry[i] = temp
}
function sort(arry) {
for (let i = 0; i < arry.length; i++) {
for (let j = 0; j < arry.length - 1 - i; j++) {
if (compare(arry[j], arry[j + 1])) {
exchange(arry, j, j + 1)
}
}
}
return arry;
}
console.log(sort(arry));
选择排序
- 算法步骤
- 首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
- 重复第二步,直到所有元素均排序完毕。
let arry = [4, 7, 2, 6, 0, 8, 9, 1, 3];
function compare(a, b) {
if (a > b) return true;
else return false;
}
function exchange(arry, i, j) {
let temp = arry[j];
arry[j] = arry[i];
arry[i] = temp;
}
function sort(arry) {
for (let i = 0; i < arry.length; i++) {
let maxIndex = 0;
for (let j = 0; j < arry.length - i; j++) {
if (compare(arry[j], arry[maxIndex]))