小白学数据结构

86 阅读4分钟

一个后进先出的数据结构

Pasted image 20230901003730.png

数组模拟栈

附带相关功能代码

const stack = [];
//入栈
stack.push(1);
//出栈
const popStack = stack.pop();

队列

一个先进先出的数据结构

Pasted image 20230901004603.png

代码模拟实现

附带相关功能代码

const queue = [];
//入栈
queue.push(1);
//出栈
queue.shift();

链表

  • 多个元素组成的列表
  • 元素存储不连续,用next指针链接在一起

Pasted image 20230901004912.png

代码模拟实现

附带相关功能代码

const a = {
    val:“a”
}
const b = {
    val:"b"
}
const c = {
    val:"c"
}
a.next = b;
b.next = c;

//遍历链表
let pointer = a;
while(pointer){
    console.log(pointer.val);
    pointer = pointer.next;
}

//出入链表值
const e = {
    val:"e"
}

b.next = e;
e.next = c;

//删除
b.next = c;

集合

一种无序且唯一的结构,js中的Set可模拟实现

结构图片想不出来了~~~~

代码模拟实现

附带相关功能代码

//去重
const arr = [1,1,2,2];
const arr2 = [...new Set(arr)];

//判断元素是否在集合中
const set = new Set(arr);
const has = set.has(1);

//求交集
const set2 = new Set([2,3]);
const set3 = new Set([...set].filter(item=>set2.has(item)));

字典

与集合类似,同样是存储唯一值的数据结构,但是,它是以键值对来进行存储的,例如js中的Map

一种分层数据的抽象模型,应用中有树的广度优先遍历和深度优先遍历,另有二叉树的先序遍历,中序遍历和后序遍历

树的深度与广度优先遍历

深度遍历

尽可能深入地搜索树的分支

Pasted image 20230901005420.png

代码模拟实现

const tree = {
    val:"a",
    children:[
        {
            val:"b",
            children:[
                {
                    val:"e",
                    children:[]
                },
                {
                    val:"f",
                    children:[]
                }
            ]
        },
        {
            val:"c",
            children:[
                {
                    val:"g",
                    children:[]
                }
            ]
        }
    ],
}
//遍历
const dfs = (root)=>{
    console.log(root.val);
    root.children.forEach(dfs);
}
dfs(tree);

广度优先遍历

先遍历离根节点最近的节点

Pasted image 20230901005522.png

代码模拟实现

const tree = {
    val:"a",
    children:[
        {
            val:"b",
            children:[
                {
                    val:"e",
                    children:[]
                },
                {
                    val:"f",
                    children:[]
                }
            ]
        },
        {
            val:"c",
            children:[
                {
                    val:"g",
                    children:[]
                }
            ]
        }
    ],
}

const bfs = (root)=>{
    const q = [root];
    while(q.lenght>0){
        const n = q.shift();
        console.log(n.val);
        n.children.forEach(child=>{
            q.push(child);
        })
    }
}
bfs(tree);

二叉树

  • 树中的子节点最多只能有2个节点
  • 在js里,通常用object来模拟实现

先序遍历

Pasted image 20230901113733.png

  1. 先访问根节点
  2. 左节点先序遍历
  3. 右节点先序遍历

先序遍历,根节点->左子树->右子树进行遍历

代码模拟实现

const tree = {
    val: 1,
    left: {
        val: 2,
        left: {
            val: 4,
            left: null,
            right: null,
        },
        right: {
            val: 5,
            left: null,
            right: null,
        },
    },
    right: {
        val: 3,
        left: {
            val: 6,
            left: null,
            right: null,
        },
        right: {
            val: 7,
            left: null,
            right: null,
        },
    },
};

const preorder = (root)=>{
	if(!root) return;
	console.log(root.val);
	preorder(root.left);
	preorder(root.right);
}

preorder(tree);

中序遍历

Pasted image 20230901114749.png

  1. 对根节点的左子树进行中序遍历
  2. 访问根节点
  3. 对根节点的右子树进行中序遍历

中序遍历,即左子树->根节点->右子树进行遍历

代码模拟实现

const tree = {
    val: 1,
    left: {
        val: 2,
        left: {
            val: 4,
            left: null,
            right: null,
        },
        right: {
            val: 5,
            left: null,
            right: null,
        },
    },
    right: {
        val: 3,
        left: {
            val: 6,
            left: null,
            right: null,
        },
        right: {
            val: 7,
            left: null,
            right: null,
        },
    },
};

const inorder = (root)=>{
	if(!root) return;
	inorder(root.left);
	console.log(root.val);
	inorder(root.right);
}

inorder(tree);

后序遍历

Pasted image 20230901120113.png

  1. 对根节点的左子树进行后序遍历
  2. 对根节点的右子树进行后序遍历
  3. 访问根节点

后序遍历,即左子树->右子树->根节点的遍历方式

代码模拟实现

const tree = {
    val: 1,
    left: {
        val: 2,
        left: {
            val: 4,
            left: null,
            right: null,
        },
        right: {
            val: 5,
            left: null,
            right: null,
        },
    },
    right: {
        val: 3,
        left: {
            val: 6,
            left: null,
            right: null,
        },
        right: {
            val: 7,
            left: null,
            right: null,
        },
    },
};

const postorder = (root)=>{
	if(!root) return;
	postorder(root.left);
	postorder(root.right);
	console.log(root.val);
}

postorder(tree);

图,一种网络结构的抽象模型,即一组由边连接的节点

图可以表示任何二元关系,例如航班

二元关系指的是一条边连了两个节点关系

Pasted image 20230901133555.png

其中,应用中有深度优先遍历和广度优先遍历

深度优先遍历

  1. 访问根节点
  2. 对根节点的没访问过的相邻节点挨个进行深度优先遍历

相关代码实现

const graph = {
    0: [1, 2],
    1: [2],
    2: [0, 3],
    3: [3]
};

const visited = new Set();

const dfs = (d)=>{
	console.log(d);
	visited.add(d);
	graph[d].forEach((g)=>{
		if(!visited.has(g)){
			dfs(g);
		}
	})
}

dfs(2);

广度优先遍历

  1. 新建一个队列且根节点入队
  2. 把队头出队并访问
  3. 把对头的没访问过的相邻节点入队
  4. 重复2,3步直到队列为空

相关代码实现

const graph = {
    0: [1, 2],
    1: [2],
    2: [0, 3],
    3: [3]
};
const visited = new Set();
visited.add(2);
const arr = [2];
while(arr.length){
	const arrShift = arr.shift();
	console.log(arrShift);
	graph[arrShift].forEach((g)=>{
		if( !visited.has(g) ){
			arr.push(g);
			visited.add(g);
		} 	
	})
}

堆,一种特殊的完全二叉树

所有的节点都大于等于即最大堆,反之最小堆

Pasted image 20230901154748.png

js中通常用数组来模拟堆

左侧子节点的位置是2 * index + 1;

右侧子节点的位置是2 * index + 2;

父节点位置是(index - 1) / 2;

相关代码,最小堆类代码实现

class MinHeap{
	constructor(){
		this.heap = [];
	}
	swap(i1,i2){
		[this.heap[i1],this.heap[i2]] = [this.heap[i2],this.heap[i1]];
	}
	getParentIndex(i){
		return (i - 1) >> 1;
	}
	shiftUp(index){
		if(index == 0) return;
		const parentIndex = this.getParentIndex(index); 
		if( this.heap[parentIndex] > this.heap[index] ){
			this.swap(parentIndex,index);
			this.shiftUp([parentIndex]);
		}
	}
	insert(value){
		this.heap.push(value);
		this.shiftUp(this.heap.length - 1);
	}	
}