feat(computer-fundamentals): add comprehensive content for computer fundamentals section

Add detailed documentation and interactive demos for computer fundamentals topics including:
- Transistor to CPU architecture
- Data encoding, storage and transmission
- Operating system concepts (processes, memory, filesystems)
- Programming language overview and paradigms
- Algorithm and data structure basics

Includes Vue component demos for key concepts with visualizations and interactive elements to enhance learning experience. All content is written in Chinese with markdown formatting and embedded components.

The commit also updates the sidebar navigation and adds new Vue components for interactive demonstrations of key computer science concepts.
This commit is contained in:
sanbuphy
2026-02-18 15:52:55 +08:00
parent 47377646df
commit d0afb042b8
27 changed files with 8843 additions and 10 deletions
@@ -0,0 +1,300 @@
<template>
<div class="adder-demo">
<div class="demo-header">
<span class="icon"></span>
<span class="title">加法器用逻辑门做加法</span>
<span class="subtitle">从逻辑门到算术运算</span>
</div>
<div class="demo-content">
<div class="adder-controls">
<div class="input-group">
<label>A:</label>
<div class="bits">
<button
v-for="(bit, i) in bitsA"
:key="'a'+i"
class="bit-btn"
:class="{ on: bit }"
@click="toggleBit('A', i)"
>{{ bit }}</button>
</div>
<span class="decimal">= {{ decimalA }}</span>
</div>
<div class="operator">+</div>
<div class="input-group">
<label>B:</label>
<div class="bits">
<button
v-for="(bit, i) in bitsB"
:key="'b'+i"
class="bit-btn"
:class="{ on: bit }"
@click="toggleBit('B', i)"
>{{ bit }}</button>
</div>
<span class="decimal">= {{ decimalB }}</span>
</div>
</div>
<div class="adder-visual">
<div class="adder-stage" v-for="(s, i) in stages" :key="i">
<div class="stage-label">{{ s.label }}</div>
<div class="stage-bits">
<span class="bit-label">A{{ 3-i }}: {{ bitsA[i] }}</span>
<span class="bit-label">B{{ 3-i }}: {{ bitsB[i] }}</span>
<span class="bit-label" v-if="i > 0">C{{ i }}: {{ carries[i-1] }}</span>
</div>
<div class="stage-result">
<span class="sum-bit">S{{ 3-i }}: {{ sumBits[i] }}</span>
<span class="carry-bit">C{{ i+1 }}: {{ carries[i] }}</span>
</div>
</div>
</div>
<div class="result-display">
<div class="result-row">
<span class="result-label">二进制结果:</span>
<span class="result-bits">{{ resultBinary }}</span>
</div>
<div class="result-row">
<span class="result-label">十进制验证:</span>
<span class="result-decimal">{{ decimalA }} + {{ decimalB }} = {{ resultDecimal }}</span>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>加法器用全加器级联实现每个全加器处理一位产生"和""进位"进位传递给下一位就像我们手算加法一样
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const bitsA = ref([0, 0, 1, 1])
const bitsB = ref([0, 0, 1, 0])
const toggleBit = (arr, i) => {
if (arr === 'A') {
bitsA.value[i] = bitsA.value[i] ? 0 : 1
} else {
bitsB.value[i] = bitsB.value[i] ? 0 : 1
}
}
const decimalA = computed(() => {
return bitsA.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3-i), 0)
})
const decimalB = computed(() => {
return bitsB.value.reduce((acc, bit, i) => acc + bit * Math.pow(2, 3-i), 0)
})
const carries = computed(() => {
const c = [0, 0, 0, 0]
for (let i = 3; i >= 0; i--) {
const sum = bitsA.value[i] + bitsB.value[i] + (i < 3 ? c[i+1] : 0)
c[i] = sum >= 2 ? 1 : 0
}
return c
})
const sumBits = computed(() => {
const s = [0, 0, 0, 0]
for (let i = 3; i >= 0; i--) {
const sum = bitsA.value[i] + bitsB.value[i] + (i < 3 ? carries.value[i+1] : 0)
s[i] = sum % 2
}
return s
})
const resultBinary = computed(() => {
const allBits = [carries.value[0], ...sumBits.value]
return allBits.join('')
})
const resultDecimal = computed(() => {
return decimalA.value + decimalB.value
})
const stages = [
{ label: '第4位 (个位)' },
{ label: '第3位' },
{ label: '第2位' },
{ label: '第1位 (最高位)' }
]
</script>
<style scoped>
.adder-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.adder-controls {
display: flex;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.input-group {
display: flex;
align-items: center;
gap: 0.5rem;
}
.input-group label {
font-weight: bold;
font-size: 0.9rem;
}
.bits {
display: flex;
gap: 0.25rem;
}
.bit-btn {
width: 28px;
height: 28px;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
transition: all 0.2s;
}
.bit-btn.on {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.decimal {
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.operator {
font-size: 1.2rem;
font-weight: bold;
color: var(--vp-c-brand);
}
.adder-visual {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
overflow-x: auto;
}
.adder-stage {
flex: 1;
min-width: 100px;
padding: 0.5rem;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
}
.stage-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
text-align: center;
margin-bottom: 0.5rem;
border-bottom: 1px solid var(--vp-c-divider);
padding-bottom: 0.25rem;
}
.stage-bits {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.75rem;
margin-bottom: 0.5rem;
}
.bit-label {
color: var(--vp-c-text-2);
}
.stage-result {
display: flex;
flex-direction: column;
gap: 0.25rem;
font-size: 0.8rem;
font-weight: bold;
}
.sum-bit {
color: var(--vp-c-brand);
}
.carry-bit {
color: var(--vp-c-warning);
}
.result-display {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.result-row {
display: flex;
gap: 0.5rem;
margin-bottom: 0.25rem;
}
.result-row:last-child {
margin-bottom: 0;
}
.result-label {
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.result-bits {
font-family: monospace;
font-weight: bold;
color: var(--vp-c-brand);
}
.result-decimal {
font-weight: bold;
color: var(--vp-c-success);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,535 @@
<template>
<div class="algorithm-demo">
<div class="demo-header">
<span class="icon">🎯</span>
<span class="title">算法思维解决问题的方法</span>
<span class="subtitle">不同策略解决不同类型的问题</span>
</div>
<div class="demo-content">
<div class="algorithm-tabs">
<button
v-for="algo in algorithms"
:key="algo.name"
:class="['tab-btn', { active: activeAlgo === algo.name }]"
@click="activeAlgo = algo.name"
>{{ algo.name }}</button>
</div>
<div class="algorithm-visual">
<div class="visual-header">
<span class="algo-name">{{ currentAlgo.name }}</span>
<span class="algo-desc">{{ currentAlgo.desc }}</span>
</div>
<div class="visual-content">
<div v-if="activeAlgo === '二分查找'" class="binary-search">
<div class="search-input">
<span>在有序数组中查找</span>
<input v-model.number="searchTarget" type="number" class="num-input" placeholder="输入数字" />
<button class="search-btn" @click="runBinarySearch">查找</button>
</div>
<div class="array-display">
<div
v-for="(num, i) in sortedArray"
:key="i"
class="array-cell"
:class="{
highlight: i >= searchRange.left && i <= searchRange.right,
found: i === foundIndex,
mid: i === midIndex
}"
>
{{ num }}
</div>
</div>
<div class="search-info" v-if="searchSteps.length">
<div class="step" v-for="(step, i) in searchSteps" :key="i">{{ step }}</div>
</div>
</div>
<div v-else-if="activeAlgo === '排序'" class="sorting">
<div class="sort-controls">
<button class="sort-btn" @click="resetArray">重置数组</button>
<button class="sort-btn" @click="runSort">开始排序</button>
</div>
<div class="array-display">
<div
v-for="(num, i) in sortArray"
:key="i"
class="array-cell"
:class="{ comparing: comparingIndices.includes(i), sorted: sortedIndices.includes(i) }"
>
{{ num }}
</div>
</div>
<div class="sort-info">{{ sortStatus }}</div>
</div>
<div v-else-if="activeAlgo === '递归'" class="recursion">
<div class="recursion-input">
<span>计算斐波那契数列第</span>
<input v-model.number="fibN" type="number" min="1" max="15" class="num-input" />
<span></span>
<button class="calc-btn" @click="calcFib">计算</button>
</div>
<div class="fib-result" v-if="fibResult !== null">
<span class="result-value">F({{ fibN }}) = {{ fibResult }}</span>
</div>
<div class="recursion-tree" v-if="fibSteps.length">
<div class="tree-title">递归调用过程</div>
<div class="tree-content">
<div v-for="(step, i) in fibSteps.slice(0, 8)" :key="i" class="tree-node">
{{ step }}
</div>
<div v-if="fibSteps.length > 8" class="tree-more">... {{ fibSteps.length }} 次调用</div>
</div>
</div>
</div>
<div v-else-if="activeAlgo === '贪心'" class="greedy">
<div class="greedy-desc">硬币找零问题用最少的硬币凑出指定金额</div>
<div class="greedy-input">
<span>目标金额</span>
<input v-model.number="coinTarget" type="number" min="1" class="num-input" />
<button class="calc-btn" @click="calcCoins">计算</button>
</div>
<div class="coins-available">
可用硬币{{ coins.join(', ') }}
</div>
<div class="coin-result" v-if="coinResult.length">
<div class="result-title">找零方案</div>
<div class="coin-list">
<span v-for="(c, i) in coinResult" :key="i" class="coin">{{ c }}</span>
</div>
<div class="result-summary"> {{ coinResult.length }} 枚硬币</div>
</div>
</div>
</div>
</div>
<div class="complexity-info">
<div class="info-title">时间复杂度速查</div>
<div class="complexity-list">
<div class="complexity-item" v-for="c in complexities" :key="c.name">
<span class="c-name">{{ c.name }}</span>
<span class="c-value" :class="c.class">{{ c.value }}</span>
<span class="c-desc">{{ c.desc }}</span>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>算法是解决问题的方法好的算法能让程序效率提升几个数量级理解算法思维比记住具体算法更重要
</div>
</div>
</template>
<script setup>
import { ref, computed, reactive } from 'vue'
const activeAlgo = ref('二分查找')
const algorithms = [
{ name: '二分查找', desc: '每次排除一半,O(log n)' },
{ name: '排序', desc: '将无序变有序' },
{ name: '递归', desc: '自己调用自己' },
{ name: '贪心', desc: '每步选最优' }
]
const currentAlgo = computed(() => {
return algorithms.find(a => a.name === activeAlgo.value)
})
const sortedArray = ref([1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25])
const searchTarget = ref(13)
const searchRange = reactive({ left: 0, right: 12 })
const foundIndex = ref(-1)
const midIndex = ref(-1)
const searchSteps = ref([])
const runBinarySearch = () => {
searchSteps.value = []
foundIndex.value = -1
midIndex.value = -1
let left = 0
let right = sortedArray.value.length - 1
while (left <= right) {
const mid = Math.floor((left + right) / 2)
midIndex.value = mid
searchRange.left = left
searchRange.right = right
searchSteps.value.push(`查找范围 [${left}, ${right}],中间位置 ${mid},值 ${sortedArray.value[mid]}`)
if (sortedArray.value[mid] === searchTarget.value) {
foundIndex.value = mid
searchSteps.value.push(`找到目标 ${searchTarget.value} 在位置 ${mid}`)
return
} else if (sortedArray.value[mid] < searchTarget.value) {
left = mid + 1
searchSteps.value.push(`${sortedArray.value[mid]} < ${searchTarget.value},在右半部分继续查找`)
} else {
right = mid - 1
searchSteps.value.push(`${sortedArray.value[mid]} > ${searchTarget.value},在左半部分继续查找`)
}
}
searchSteps.value.push(`未找到目标 ${searchTarget.value}`)
}
const sortArray = ref([64, 34, 25, 12, 22, 11, 90, 45])
const comparingIndices = ref([])
const sortedIndices = ref([])
const sortStatus = ref('点击"开始排序"观察冒泡排序过程')
const resetArray = () => {
sortArray.value = [64, 34, 25, 12, 22, 11, 90, 45]
comparingIndices.value = []
sortedIndices.value = []
sortStatus.value = '数组已重置'
}
const runSort = async () => {
sortedIndices.value = []
const arr = [...sortArray.value]
const n = arr.length
for (let i = 0; i < n - 1; i++) {
for (let j = 0; j < n - i - 1; j++) {
comparingIndices.value = [j, j + 1]
sortStatus.value = `比较 ${arr[j]}${arr[j + 1]}`
await new Promise(r => setTimeout(r, 300))
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
sortArray.value = [...arr]
sortStatus.value = `交换 ${arr[j + 1]}${arr[j]}`
await new Promise(r => setTimeout(r, 200))
}
}
sortedIndices.value.push(n - i - 1)
}
sortedIndices.value.push(0)
comparingIndices.value = []
sortStatus.value = '排序完成!'
}
const fibN = ref(8)
const fibResult = ref(null)
const fibSteps = ref([])
const calcFib = () => {
fibSteps.value = []
const fib = (n) => {
fibSteps.value.push(`fib(${n})`)
if (n <= 1) return n
return fib(n - 1) + fib(n - 2)
}
fibResult.value = fib(fibN.value)
}
const coinTarget = ref(67)
const coins = [100, 50, 20, 10, 5, 1]
const coinResult = ref([])
const calcCoins = () => {
coinResult.value = []
let remaining = coinTarget.value
for (const coin of coins) {
while (remaining >= coin) {
coinResult.value.push(coin)
remaining -= coin
}
}
}
const complexities = [
{ name: 'O(1)', value: '常数', desc: '最优,如数组访问', class: 'good' },
{ name: 'O(log n)', value: '对数', desc: '很好,如二分查找', class: 'good' },
{ name: 'O(n)', value: '线性', desc: '一般,如遍历', class: 'mid' },
{ name: 'O(n log n)', value: '线性对数', desc: '可接受,如快速排序', class: 'mid' },
{ name: 'O(n²)', value: '平方', desc: '较慢,如冒泡排序', class: 'bad' },
{ name: 'O(2ⁿ)', value: '指数', desc: '很慢,如暴力递归', class: 'bad' }
]
</script>
<style scoped>
.algorithm-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.algorithm-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.tab-btn {
padding: 0.4rem 0.8rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.algorithm-visual {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.visual-header {
margin-bottom: 0.75rem;
}
.algo-name {
font-weight: bold;
font-size: 1rem;
}
.algo-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-left: 0.5rem;
}
.search-input, .greedy-input, .recursion-input {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
flex-wrap: wrap;
}
.num-input {
width: 60px;
padding: 0.25rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg-alt);
}
.search-btn, .sort-btn, .calc-btn {
padding: 0.25rem 0.75rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
}
.array-display {
display: flex;
gap: 2px;
margin-bottom: 0.75rem;
flex-wrap: wrap;
}
.array-cell {
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
font-weight: bold;
font-size: 0.85rem;
min-width: 32px;
text-align: center;
}
.array-cell.highlight {
background: var(--vp-c-brand-soft);
}
.array-cell.found {
background: var(--vp-c-success);
color: white;
}
.array-cell.mid {
border: 2px solid var(--vp-c-brand);
}
.array-cell.comparing {
background: var(--vp-c-warning-soft);
}
.array-cell.sorted {
background: var(--vp-c-success-soft);
}
.search-info, .sort-info {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.step {
padding: 0.15rem 0;
}
.sort-controls {
display: flex;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.fib-result {
font-size: 1.1rem;
font-weight: bold;
color: var(--vp-c-brand);
margin-bottom: 0.5rem;
}
.recursion-tree {
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
}
.tree-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.25rem;
}
.tree-content {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
}
.tree-node {
font-size: 0.75rem;
font-family: monospace;
background: var(--vp-c-bg);
padding: 0.15rem 0.4rem;
border-radius: 3px;
}
.tree-more {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.greedy-desc {
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.coins-available {
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
}
.coin-result {
margin-top: 0.5rem;
}
.result-title {
font-weight: bold;
font-size: 0.85rem;
}
.coin-list {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
margin: 0.25rem 0;
}
.coin {
padding: 0.25rem 0.5rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-size: 0.8rem;
}
.result-summary {
font-size: 0.85rem;
color: var(--vp-c-success);
font-weight: bold;
}
.complexity-info {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.info-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.complexity-list {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.complexity-item {
display: flex;
gap: 0.5rem;
font-size: 0.8rem;
}
.c-name {
font-family: monospace;
font-weight: bold;
min-width: 60px;
}
.c-value {
min-width: 50px;
}
.c-value.good { color: var(--vp-c-success); }
.c-value.mid { color: var(--vp-c-warning); }
.c-value.bad { color: var(--vp-c-danger); }
.c-desc {
color: var(--vp-c-text-2);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,598 @@
<template>
<div class="compiler-demo">
<div class="demo-header">
<span class="icon"></span>
<span class="title">编译器工作流程</span>
<span class="subtitle">从源代码到机器码的旅程</span>
</div>
<div class="demo-content">
<div class="pipeline-visual">
<div class="pipeline-title">编译流程</div>
<div class="pipeline-stages">
<div
v-for="(stage, i) in stages"
:key="i"
:class="['stage', { active: activeStage === i }]"
@click="activeStage = i"
>
<div class="stage-num">{{ i + 1 }}</div>
<div class="stage-name">{{ stage.name }}</div>
<div class="stage-output">{{ stage.output }}</div>
</div>
<div class="stage-arrow" v-for="i in stages.length - 1" :key="'arrow-' + i"></div>
</div>
</div>
<div class="stage-detail" v-if="currentStage">
<div class="detail-header">
<span class="detail-name">{{ currentStage.name }}</span>
</div>
<div class="detail-desc">{{ currentStage.desc }}</div>
<div class="detail-tasks">
<div class="task-title">主要任务</div>
<ul>
<li v-for="(task, j) in currentStage.tasks" :key="j">{{ task }}</li>
</ul>
</div>
<div class="detail-example">
<div class="example-title">示例</div>
<pre><code>{{ currentStage.example }}</code></pre>
</div>
</div>
<div class="interactive-demo">
<div class="demo-title">词法分析演示</div>
<div class="lexer-input">
<label>输入代码</label>
<input v-model="sourceCode" type="text" placeholder="例如: int x = 10 + 5;" />
</div>
<div class="lexer-output">
<div class="output-title">词法单元 (Tokens)</div>
<div class="tokens">
<div
v-for="(token, i) in tokens"
:key="i"
:class="['token', token.type]"
>
<span class="token-value">{{ token.value }}</span>
<span class="token-type">{{ token.type }}</span>
</div>
</div>
</div>
</div>
<div class="ast-demo">
<div class="demo-title">语法树 (AST) 可视化</div>
<div class="ast-input">
<label>表达式</label>
<input v-model="expression" type="text" placeholder="例如: 1 + 2 * 3" />
</div>
<div class="ast-visual">
<div class="ast-node root" v-if="ast">
<div class="node-value">{{ ast.value }}</div>
<div class="node-children" v-if="ast.left || ast.right">
<div class="ast-node left" v-if="ast.left">
<div class="node-value">{{ ast.left.value }}</div>
</div>
<div class="ast-node right" v-if="ast.right">
<div class="node-value">{{ ast.right.value }}</div>
</div>
</div>
</div>
</div>
</div>
<div class="comparison-section">
<div class="section-title">编译型 vs 解释型 vs JIT</div>
<div class="comparison-grid">
<div class="comparison-item" v-for="(item, i) in executionModels" :key="i">
<div class="item-name">{{ item.name }}</div>
<div class="item-flow">{{ item.flow }}</div>
<div class="item-pros">{{ item.pros }}</div>
<div class="item-cons">{{ item.cons }}</div>
<div class="item-langs">{{ item.langs }}</div>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>编译器将人类可读的源代码转换为机器可执行的指令主要阶段包括词法分析语法分析语义分析中间代码生成优化和目标代码生成
</div>
</div>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
const activeStage = ref(0)
const stages = [
{
name: '词法分析',
output: 'Token 流',
desc: '将源代码分解为一个个词法单元(Token)',
tasks: ['识别关键字、标识符、字面量、运算符', '过滤空白和注释', '记录位置信息'],
example: `源代码: int x = 10;
Tokens: [int][x][=][10][;]`
},
{
name: '语法分析',
output: 'AST',
desc: '根据语法规则,将 Token 流组织成语法树',
tasks: ['构建抽象语法树 (AST)', '检查语法错误', '确定运算优先级'],
example: `表达式: 1 + 2 * 3
AST:
+
/ \\
1 *
/ \\
2 3`
},
{
name: '语义分析',
output: '带类型的 AST',
desc: '检查语义正确性,进行类型检查',
tasks: ['类型检查', '作用域分析', '符号表构建', '类型推断'],
example: `int x = "hello"; // 类型错误!
int y = 10 + 5; // 正确`
},
{
name: '中间代码',
output: 'IR',
desc: '生成平台无关的中间表示',
tasks: ['生成三地址码或 SSA', '便于优化', '支持多目标平台'],
example: `x = 10 + 5
// 三地址码:
t1 = 10 + 5
x = t1`
},
{
name: '优化',
output: '优化后的 IR',
desc: '对中间代码进行各种优化',
tasks: ['常量折叠', '死代码消除', '循环优化', '内联展开'],
example: `// 优化前
x = 10 + 5
y = x * 2
// 优化后(常量折叠)
x = 15
y = 30`
},
{
name: '代码生成',
output: '机器码',
desc: '生成目标机器的机器码',
tasks: ['指令选择', '寄存器分配', '指令调度', '生成可执行文件'],
example: `// x = 15 的汇编
mov eax, 15
mov [x], eax`
}
]
const currentStage = computed(() => stages[activeStage.value])
const sourceCode = ref('int x = 10 + 5;')
const keywords = ['int', 'float', 'if', 'else', 'while', 'for', 'return', 'void', 'class', 'public', 'private']
const operators = ['+', '-', '*', '/', '=', '==', '!=', '<', '>', '<=', '>=']
const tokens = computed(() => {
const code = sourceCode.value
if (!code.trim()) return []
const result = []
const words = code.split(/(\s+|[;,\(\)\{\}\[\]])/)
for (const word of words) {
if (!word.trim()) continue
if (keywords.includes(word)) {
result.push({ value: word, type: 'keyword' })
} else if (operators.includes(word)) {
result.push({ value: word, type: 'operator' })
} else if (/^\d+$/.test(word)) {
result.push({ value: word, type: 'number' })
} else if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(word)) {
result.push({ value: word, type: 'identifier' })
} else if (word === ';') {
result.push({ value: word, type: 'punctuation' })
} else {
result.push({ value: word, type: 'unknown' })
}
}
return result
})
const expression = ref('1 + 2 * 3')
const ast = computed(() => {
const expr = expression.value.trim()
if (!expr) return null
const parseExpression = (str) => {
str = str.trim()
const addSubMatch = str.match(/^(.+?)\s*([+-])\s*(.+)$/)
if (addSubMatch) {
return {
value: addSubMatch[2],
left: parseExpression(addSubMatch[1]),
right: parseExpression(addSubMatch[3])
}
}
const mulDivMatch = str.match(/^(.+?)\s*([*/])\s*(.+)$/)
if (mulDivMatch) {
return {
value: mulDivMatch[2],
left: parseExpression(mulDivMatch[1]),
right: parseExpression(mulDivMatch[3])
}
}
if (/^\d+$/.test(str)) {
return { value: str }
}
return { value: str }
}
return parseExpression(expr)
})
const executionModels = [
{
name: '编译型',
flow: '源码 → 编译 → 机器码 → 执行',
pros: '执行快,编译期检查',
cons: '编译慢,跨平台难',
langs: 'C, C++, Rust, Go'
},
{
name: '解释型',
flow: '源码 → 解释器 → 逐行执行',
pros: '跨平台,开发快',
cons: '执行慢,运行时检查',
langs: 'Python, Ruby, PHP'
},
{
name: 'JIT',
flow: '源码 → 字节码 → JIT编译 → 执行',
pros: '兼顾性能和跨平台',
cons: '启动慢,内存占用大',
langs: 'Java, JavaScript(V8)'
}
]
</script>
<style scoped>
.compiler-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.pipeline-visual {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.pipeline-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.pipeline-stages {
display: flex;
align-items: center;
gap: 0.25rem;
flex-wrap: wrap;
position: relative;
}
.stage {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.4rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
cursor: pointer;
min-width: 80px;
border: 2px solid transparent;
}
.stage:hover {
background: var(--vp-c-bg-soft);
}
.stage.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.stage-num {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-brand);
color: white;
border-radius: 50%;
font-size: 0.7rem;
font-weight: bold;
margin-bottom: 0.25rem;
}
.stage-name {
font-size: 0.75rem;
font-weight: bold;
}
.stage-output {
font-size: 0.65rem;
color: var(--vp-c-text-2);
}
.stage-arrow {
color: var(--vp-c-text-3);
font-size: 0.8rem;
}
.stage-detail {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.detail-header {
margin-bottom: 0.5rem;
}
.detail-name {
font-weight: bold;
font-size: 1rem;
color: var(--vp-c-brand);
}
.detail-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
}
.detail-tasks {
margin-bottom: 0.5rem;
}
.task-title, .example-title {
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 0.25rem;
}
.detail-tasks ul {
margin: 0;
padding-left: 1rem;
font-size: 0.8rem;
}
.detail-example {
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
}
pre {
margin: 0;
font-size: 0.75rem;
white-space: pre-wrap;
}
code {
font-family: monospace;
}
.interactive-demo, .ast-demo {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.demo-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.lexer-input, .ast-input {
margin-bottom: 0.5rem;
}
.lexer-input label, .ast-input label {
display: block;
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-bottom: 0.25rem;
}
.lexer-input input, .ast-input input {
width: 100%;
padding: 0.4rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg-alt);
font-family: monospace;
font-size: 0.85rem;
}
.output-title {
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-bottom: 0.25rem;
}
.tokens {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.token {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.25rem 0.4rem;
border-radius: 4px;
font-size: 0.75rem;
}
.token.keyword { background: #d4edda; }
.token.operator { background: #fff3cd; }
.token.number { background: #cce5ff; }
.token.identifier { background: #e2e3e5; }
.token.punctuation { background: #f8d7da; }
.token-value {
font-family: monospace;
font-weight: bold;
}
.token-type {
font-size: 0.65rem;
color: var(--vp-c-text-2);
}
.ast-visual {
display: flex;
justify-content: center;
padding: 1rem;
}
.ast-node {
display: flex;
flex-direction: column;
align-items: center;
}
.node-value {
padding: 0.4rem 0.6rem;
background: var(--vp-c-brand);
color: white;
border-radius: 4px;
font-weight: bold;
font-family: monospace;
}
.node-children {
display: flex;
gap: 1rem;
margin-top: 0.5rem;
position: relative;
}
.node-children::before {
content: '';
position: absolute;
top: -0.5rem;
left: 50%;
width: 1px;
height: 0.5rem;
background: var(--vp-c-divider);
}
.ast-node.left .node-value,
.ast-node.right .node-value {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand);
}
.comparison-section {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.section-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.comparison-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 0.5rem;
}
.comparison-item {
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
}
.item-name {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.25rem;
color: var(--vp-c-brand);
}
.item-flow {
font-size: 0.75rem;
font-family: monospace;
margin-bottom: 0.25rem;
}
.item-pros, .item-cons {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.item-pros::before { content: '✅ '; }
.item-cons::before { content: '❌ '; }
.item-langs {
font-size: 0.7rem;
color: var(--vp-c-text-3);
margin-top: 0.25rem;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,245 @@
<template>
<div class="cpu-arch-demo">
<div class="demo-header">
<span class="icon">🖥</span>
<span class="title">CPU 架构全貌</span>
<span class="subtitle">从门电路到处理器</span>
</div>
<div class="demo-content">
<div class="architecture-layers">
<div
v-for="(layer, i) in layers"
:key="layer.name"
class="layer"
:class="{ active: activeLayer === i }"
@click="activeLayer = activeLayer === i ? null : i"
>
<div class="layer-header">
<span class="layer-icon">{{ layer.icon }}</span>
<span class="layer-name">{{ layer.name }}</span>
<span class="layer-count">{{ layer.count }}</span>
</div>
<Transition name="fade">
<div v-if="activeLayer === i" class="layer-detail">
<p class="detail-desc">{{ layer.desc }}</p>
<div class="detail-example">
<span class="example-label">🌰 例子</span>
<span class="example-content">{{ layer.example }}</span>
</div>
</div>
</Transition>
</div>
</div>
<div class="cpu-components">
<div class="comp-title">CPU 核心组件</div>
<div class="comp-grid">
<div class="comp-item" v-for="comp in components" :key="comp.name">
<span class="comp-icon">{{ comp.icon }}</span>
<span class="comp-name">{{ comp.name }}</span>
<span class="comp-desc">{{ comp.desc }}</span>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>CPU是层次化构建的晶体管逻辑门功能单元处理器每一层都是下一层的"积木"最终形成能执行程序的"大脑"
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const activeLayer = ref(null)
const layers = [
{
name: '晶体管',
icon: '⚡',
count: '数十亿个',
desc: '最基本的开关单元,用半导体材料制成。现代CPU包含数十亿个晶体管。',
example: 'Apple M2 芯片有约 200 亿个晶体管'
},
{
name: '逻辑门',
icon: '🔌',
count: '数亿个',
desc: '由多个晶体管组成,实现基本逻辑运算(AND、OR、NOT等)。',
example: '一个 AND 门需要 2-6 个晶体管'
},
{
name: '功能单元',
icon: '🔧',
count: '数百个',
desc: '由逻辑门组成,实现特定功能:加法器、多路选择器、寄存器等。',
example: '一个 64 位加法器需要约 1000 个逻辑门'
},
{
name: 'CPU 核心',
icon: '🧠',
count: '1-128个',
desc: '包含完整的运算和控制能力,能独立执行指令流。',
example: 'Intel i9-13900K 有 24 核心'
}
]
const components = [
{ icon: '📊', name: 'ALU', desc: '算术逻辑单元,做加减乘除和逻辑运算' },
{ icon: '📁', name: '寄存器', desc: '超高速存储,存放正在处理的数据' },
{ icon: '🎮', name: '控制器', desc: '指挥官,解码指令并协调各部件' },
{ icon: '🚌', name: '总线', desc: '数据高速公路,连接各部件' }
]
</script>
<style scoped>
.cpu-arch-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.architecture-layers {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
.layer {
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
border-radius: 6px;
padding: 0.5rem 0.75rem;
cursor: pointer;
transition: all 0.2s;
}
.layer:hover {
border-color: var(--vp-c-brand);
}
.layer.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.layer-header {
display: flex;
align-items: center;
gap: 0.5rem;
}
.layer-icon {
font-size: 1rem;
}
.layer-name {
font-weight: bold;
font-size: 0.9rem;
}
.layer-count {
margin-left: auto;
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.layer-detail {
margin-top: 0.5rem;
padding-top: 0.5rem;
border-top: 1px solid var(--vp-c-divider);
}
.detail-desc {
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.detail-example {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.example-label {
font-weight: bold;
}
.cpu-components {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.comp-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.comp-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
}
.comp-item {
display: flex;
flex-direction: column;
padding: 0.5rem;
background: var(--vp-c-bg);
border-radius: 4px;
}
.comp-icon {
font-size: 1rem;
margin-bottom: 0.25rem;
}
.comp-name {
font-weight: bold;
font-size: 0.85rem;
}
.comp-desc {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.2s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,529 @@
<template>
<div class="data-structure-demo">
<div class="demo-header">
<span class="icon">📦</span>
<span class="title">数据结构数据的"容器"</span>
<span class="subtitle">不同场景选择不同的存储方式</span>
</div>
<div class="demo-content">
<div class="structure-tabs">
<button
v-for="s in structures"
:key="s.name"
:class="['tab-btn', { active: activeStructure === s.name }]"
@click="activeStructure = s.name"
>{{ s.name }}</button>
</div>
<div class="structure-visual">
<div class="visual-header">
<span class="structure-name">{{ currentStructure.name }}</span>
<span class="structure-desc">{{ currentStructure.desc }}</span>
</div>
<div class="visual-content">
<div v-if="activeStructure === '数组'" class="array-visual">
<div class="array-container">
<div v-for="(item, i) in arrayData" :key="i" class="array-item">
<span class="index">{{ i }}</span>
<span class="value">{{ item }}</span>
</div>
</div>
<div class="operation-hint">访问 arr[2] = O(1)插入/删除 = O(n)</div>
</div>
<div v-else-if="activeStructure === '链表'" class="linked-visual">
<div class="linked-container">
<div v-for="(item, i) in linkedData" :key="i" class="linked-node">
<span class="node-value">{{ item.value }}</span>
<span class="node-arrow" v-if="i < linkedData.length - 1"></span>
</div>
</div>
<div class="operation-hint">访问第 n = O(n)插入/删除 = O(1)</div>
</div>
<div v-else-if="activeStructure === '栈'" class="stack-visual">
<div class="stack-container">
<div v-for="(item, i) in stackData" :key="i" class="stack-item">
{{ item }}
</div>
<div class="stack-bottom">栈底</div>
</div>
<div class="stack-ops">
<button class="op-btn" @click="pushStack">入栈 Push</button>
<button class="op-btn" @click="popStack">出栈 Pop</button>
</div>
<div class="operation-hint">后进先出 (LIFO)操作都是 O(1)</div>
</div>
<div v-else-if="activeStructure === '队列'" class="queue-visual">
<div class="queue-container">
<span class="queue-label"> </span>
<div v-for="(item, i) in queueData" :key="i" class="queue-item">
{{ item }}
</div>
<span class="queue-label"> </span>
</div>
<div class="queue-ops">
<button class="op-btn" @click="enqueue">入队</button>
<button class="op-btn" @click="dequeue">出队</button>
</div>
<div class="operation-hint">先进先出 (FIFO)操作都是 O(1)</div>
</div>
<div v-else-if="activeStructure === '哈希表'" class="hash-visual">
<div class="hash-container">
<div v-for="(bucket, i) in hashData" :key="i" class="hash-bucket">
<span class="bucket-index">{{ i }}</span>
<div class="bucket-items">
<span v-for="(item, j) in bucket" :key="j" class="bucket-item">{{ item }}</span>
</div>
</div>
</div>
<div class="operation-hint">查找/插入/删除平均 O(1)最坏 O(n)</div>
</div>
<div v-else-if="activeStructure === '树'" class="tree-visual">
<div class="tree-container">
<div class="tree-level">
<div class="tree-node root">{{ treeData.value }}</div>
</div>
<div class="tree-level">
<div class="tree-node">{{ treeData.left?.value }}</div>
<div class="tree-node">{{ treeData.right?.value }}</div>
</div>
<div class="tree-level">
<div class="tree-node leaf">{{ treeData.left?.left?.value }}</div>
<div class="tree-node leaf">{{ treeData.left?.right?.value }}</div>
<div class="tree-node leaf">{{ treeData.right?.left?.value }}</div>
<div class="tree-node leaf">{{ treeData.right?.right?.value }}</div>
</div>
</div>
<div class="operation-hint">查找/插入/删除 O(log n)遍历 O(n)</div>
</div>
</div>
</div>
<div class="complexity-table">
<div class="table-title">时间复杂度对比</div>
<table>
<thead>
<tr>
<th>操作</th>
<th>数组</th>
<th>链表</th>
<th>哈希表</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>访问</td>
<td class="good">O(1)</td>
<td class="bad">O(n)</td>
<td class="good">O(1)</td>
<td class="mid">O(log n)</td>
</tr>
<tr>
<td>查找</td>
<td class="bad">O(n)</td>
<td class="bad">O(n)</td>
<td class="good">O(1)</td>
<td class="mid">O(log n)</td>
</tr>
<tr>
<td>插入</td>
<td class="bad">O(n)</td>
<td class="good">O(1)</td>
<td class="good">O(1)</td>
<td class="mid">O(log n)</td>
</tr>
<tr>
<td>删除</td>
<td class="bad">O(n)</td>
<td class="good">O(1)</td>
<td class="good">O(1)</td>
<td class="mid">O(log n)</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>数据结构是数据的"容器"不同的容器有不同的特点选择合适的数据结构能让程序效率提升几个数量级
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeStructure = ref('数组')
const structures = [
{ name: '数组', desc: '连续内存,索引访问快' },
{ name: '链表', desc: '节点相连,插入删除快' },
{ name: '栈', desc: '后进先出,函数调用用' },
{ name: '队列', desc: '先进先出,任务调度用' },
{ name: '哈希表', desc: '键值对,查找最快' },
{ name: '树', desc: '层次结构,排序搜索' }
]
const currentStructure = computed(() => {
return structures.find(s => s.name === activeStructure.value)
})
const arrayData = ref([10, 20, 30, 40, 50, 60, 70, 80])
const linkedData = ref([
{ value: 10 },
{ value: 20 },
{ value: 30 },
{ value: 40 },
{ value: 50 }
])
const stackData = ref(['A', 'B', 'C'])
const stackCounter = ref(68)
const pushStack = () => {
stackCounter.value++
stackData.value.push(String.fromCharCode(stackCounter.value))
}
const popStack = () => {
if (stackData.value.length > 0) {
stackData.value.pop()
}
}
const queueData = ref(['任务1', '任务2', '任务3'])
const queueCounter = ref(3)
const enqueue = () => {
queueCounter.value++
queueData.value.push(`任务${queueCounter.value}`)
}
const dequeue = () => {
if (queueData.value.length > 0) {
queueData.value.shift()
}
}
const hashData = ref([
['apple', 'ant'],
['banana'],
[],
['cat', 'car', 'cup'],
['dog'],
[],
['egg', 'eye']
])
const treeData = ref({
value: 50,
left: {
value: 30,
left: { value: 20 },
right: { value: 40 }
},
right: {
value: 70,
left: { value: 60 },
right: { value: 80 }
}
})
</script>
<style scoped>
.data-structure-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.structure-tabs {
display: flex;
flex-wrap: wrap;
gap: 0.25rem;
margin-bottom: 1rem;
}
.tab-btn {
padding: 0.35rem 0.6rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.structure-visual {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.visual-header {
margin-bottom: 0.75rem;
}
.structure-name {
font-weight: bold;
font-size: 1rem;
}
.structure-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-left: 0.5rem;
}
.visual-content {
min-height: 120px;
}
.array-container {
display: flex;
gap: 2px;
}
.array-item {
display: flex;
flex-direction: column;
align-items: center;
border: 1px solid var(--vp-c-divider);
padding: 0.25rem 0.5rem;
background: var(--vp-c-bg-alt);
}
.index {
font-size: 0.65rem;
color: var(--vp-c-text-3);
}
.value {
font-weight: bold;
font-size: 0.9rem;
}
.linked-container {
display: flex;
align-items: center;
gap: 0;
}
.linked-node {
display: flex;
align-items: center;
}
.node-value {
padding: 0.5rem 0.75rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-weight: bold;
}
.node-arrow {
margin: 0 0.25rem;
color: var(--vp-c-brand);
}
.stack-container {
display: flex;
flex-direction: column-reverse;
align-items: center;
gap: 2px;
}
.stack-item {
padding: 0.5rem 1.5rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-weight: bold;
}
.stack-bottom {
font-size: 0.75rem;
color: var(--vp-c-text-3);
margin-top: 0.25rem;
}
.stack-ops, .queue-ops {
display: flex;
gap: 0.5rem;
margin-top: 0.5rem;
justify-content: center;
}
.op-btn {
padding: 0.35rem 0.75rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
}
.queue-container {
display: flex;
align-items: center;
gap: 0.25rem;
}
.queue-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.queue-item {
padding: 0.5rem 0.75rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-weight: bold;
}
.hash-container {
display: flex;
flex-direction: column;
gap: 2px;
}
.hash-bucket {
display: flex;
align-items: center;
gap: 0.5rem;
}
.bucket-index {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-bg-alt);
border-radius: 4px;
font-size: 0.75rem;
font-weight: bold;
}
.bucket-items {
display: flex;
gap: 0.25rem;
}
.bucket-item {
padding: 0.25rem 0.5rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-size: 0.8rem;
}
.tree-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
}
.tree-level {
display: flex;
gap: 0.5rem;
}
.tree-node {
padding: 0.5rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-weight: bold;
min-width: 40px;
text-align: center;
}
.tree-node.root {
background: var(--vp-c-brand);
color: white;
}
.tree-node.leaf {
background: var(--vp-c-bg-alt);
}
.operation-hint {
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-top: 0.5rem;
text-align: center;
}
.complexity-table {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.table-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.8rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.35rem;
text-align: center;
}
th {
background: var(--vp-c-bg);
}
.good { color: var(--vp-c-success); font-weight: bold; }
.mid { color: var(--vp-c-warning); }
.bad { color: var(--vp-c-danger); }
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,265 @@
<template>
<div class="encoding-demo">
<div class="demo-header">
<span class="icon">🔢</span>
<span class="title">数字编码 0 1 表示一切</span>
<span class="subtitle">字符数字图像如何变成二进制</span>
</div>
<div class="demo-content">
<div class="encoding-tabs">
<button
v-for="tab in tabs"
:key="tab.name"
:class="['tab-btn', { active: activeTab === tab.name }]"
@click="activeTab = tab.name"
>{{ tab.label }}</button>
</div>
<div class="encoding-area">
<div class="input-section">
<label>输入内容</label>
<input
v-model="inputValue"
class="input-field"
:placeholder="currentTab.placeholder"
/>
</div>
<div class="output-section">
<div class="output-label">编码结果</div>
<div class="output-box">
<code>{{ encodedResult }}</code>
</div>
<div class="output-info" v-if="currentTab.name === 'text'">
<span>字符数: {{ inputValue.length }}</span>
<span>字节数: {{ byteCount }}</span>
</div>
</div>
<div class="encoding-table" v-if="currentTab.name === 'text' && inputValue">
<div class="table-title">字符编码详情</div>
<div class="char-list">
<div
v-for="(char, i) in inputValue.slice(0, 10)"
:key="i"
class="char-item"
>
<span class="char-display">{{ char }}</span>
<span class="char-unicode">U+{{ char.charCodeAt(0).toString(16).toUpperCase().padStart(4, '0') }}</span>
<span class="char-binary">{{ char.charCodeAt(0).toString(2).padStart(8, '0') }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>所有数据最终都要变成 0 1不同类型的数据用不同的编码规则字符用 ASCII/Unicode数字用二进制图像用像素值
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeTab = ref('text')
const inputValue = ref('Hello')
const tabs = [
{ name: 'text', label: '文本编码' },
{ name: 'number', label: '数字编码' },
{ name: 'color', label: '颜色编码' }
]
const currentTab = computed(() => {
const tab = tabs.find(t => t.name === activeTab.value)
return {
...tab,
placeholder: tab.name === 'text' ? '输入文字...' :
tab.name === 'number' ? '输入数字...' : '输入颜色值(如 #FF5733)'
}
})
const encodedResult = computed(() => {
if (!inputValue.value) return ''
switch (activeTab.value) {
case 'text':
return Array.from(inputValue.value)
.map(c => c.charCodeAt(0).toString(2).padStart(8, '0'))
.join(' ')
case 'number':
const num = parseInt(inputValue.value)
if (isNaN(num)) return '请输入有效数字'
return num.toString(2)
case 'color':
const hex = inputValue.value.replace('#', '')
if (!/^[0-9A-Fa-f]{6}$/.test(hex)) return '请输入有效的颜色值(如 #FF5733)'
const r = parseInt(hex.slice(0, 2), 16)
const g = parseInt(hex.slice(2, 4), 16)
const b = parseInt(hex.slice(4, 6), 16)
return `R: ${r.toString(2).padStart(8, '0')} G: ${g.toString(2).padStart(8, '0')} B: ${b.toString(2).padStart(8, '0')}`
default:
return ''
}
})
const byteCount = computed(() => {
return new Blob([inputValue.value]).size
})
</script>
<style scoped>
.encoding-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.encoding-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.tab-btn {
padding: 0.4rem 0.8rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.encoding-area {
display: flex;
flex-direction: column;
gap: 1rem;
}
.input-section {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.input-section label {
font-size: 0.85rem;
font-weight: bold;
}
.input-field {
padding: 0.5rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg);
font-size: 1rem;
}
.output-section {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.output-label {
font-size: 0.85rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.output-box {
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
font-family: monospace;
font-size: 0.85rem;
word-break: break-all;
}
.output-info {
display: flex;
gap: 1rem;
margin-top: 0.5rem;
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.encoding-table {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.table-title {
font-size: 0.85rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.char-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.char-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.5rem;
background: var(--vp-c-bg);
border-radius: 4px;
min-width: 80px;
}
.char-display {
font-size: 1.2rem;
font-weight: bold;
}
.char-unicode {
font-size: 0.7rem;
color: var(--vp-c-brand);
}
.char-binary {
font-size: 0.65rem;
font-family: monospace;
color: var(--vp-c-text-2);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,292 @@
<template>
<div class="filesystem-demo">
<div class="demo-header">
<span class="icon">📁</span>
<span class="title">文件系统数据的"档案柜"</span>
<span class="subtitle">操作系统如何组织和管理文件</span>
</div>
<div class="demo-content">
<div class="fs-tree">
<div class="tree-header">
<span class="header-icon">📂</span>
<span>目录结构</span>
</div>
<div class="tree-content">
<div
v-for="item in fileTree"
:key="item.path"
class="tree-item"
:class="{ selected: selectedItem === item.path }"
:style="{ paddingLeft: (item.level * 12) + 'px' }"
@click="selectItem(item)"
>
<span class="item-icon">{{ item.icon }}</span>
<span class="item-name">{{ item.name }}</span>
</div>
</div>
</div>
<div class="fs-detail">
<div class="detail-header">
<span class="detail-icon">{{ selectedItemInfo?.icon }}</span>
<span class="detail-name">{{ selectedItemInfo?.name }}</span>
</div>
<div class="detail-info" v-if="selectedItemInfo">
<div class="info-row">
<span class="info-label">类型</span>
<span class="info-value">{{ selectedItemInfo.type }}</span>
</div>
<div class="info-row">
<span class="info-label">路径</span>
<span class="info-value">{{ selectedItemInfo.path }}</span>
</div>
<div class="info-row" v-if="selectedItemInfo.type === '文件'">
<span class="info-label">大小</span>
<span class="info-value">{{ selectedItemInfo.size }}</span>
</div>
<div class="info-row">
<span class="info-label">权限</span>
<span class="info-value">{{ selectedItemInfo.permission }}</span>
</div>
</div>
<div class="inode-info" v-if="selectedItemInfo?.type === '文件'">
<div class="inode-title">inode 信息</div>
<div class="inode-visual">
<div class="inode-block">
<span class="inode-label">inode 编号</span>
<span class="inode-value">{{ selectedItemInfo.inode }}</span>
</div>
<div class="inode-block">
<span class="inode-label">数据块</span>
<div class="data-blocks">
<span v-for="b in selectedItemInfo.blocks" :key="b" class="block">{{ b }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>文件系统用"目录树"组织文件"inode"记录文件元数据文件名只是给人看的系统通过 inode 编号找到真正的数据
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const selectedItem = ref('/home')
const fileTree = ref([
{ name: '/', path: '/', icon: '📁', level: 0, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'home', path: '/home', icon: '📁', level: 1, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'user', path: '/home/user', icon: '📁', level: 2, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'documents', path: '/home/user/documents', icon: '📁', level: 3, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'report.pdf', path: '/home/user/documents/report.pdf', icon: '📄', level: 4, type: '文件', size: '2.5MB', permission: 'rw-r--r--', inode: 12345, blocks: ['块1', '块2', '块3'] },
{ name: 'photos', path: '/home/user/photos', icon: '📁', level: 3, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'vacation.jpg', path: '/home/user/photos/vacation.jpg', icon: '🖼️', level: 4, type: '文件', size: '4.2MB', permission: 'rw-r--r--', inode: 12346, blocks: ['块4', '块5', '块6', '块7'] },
{ name: 'etc', path: '/etc', icon: '📁', level: 1, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'config.yml', path: '/etc/config.yml', icon: '⚙️', level: 2, type: '文件', size: '1.2KB', permission: 'rw-r--r--', inode: 10001, blocks: ['块8'] },
{ name: 'var', path: '/var', icon: '📁', level: 1, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'log', path: '/var/log', icon: '📁', level: 2, type: '目录', permission: 'rwxr-xr-x' },
{ name: 'system.log', path: '/var/log/system.log', icon: '📝', level: 3, type: '文件', size: '128MB', permission: 'rw-r-----', inode: 20001, blocks: ['块9', '块10', '...'] }
])
const selectedItemInfo = computed(() => {
return fileTree.value.find(item => item.path === selectedItem.value)
})
const selectItem = (item) => {
selectedItem.value = item.path
}
</script>
<style scoped>
.filesystem-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.fs-tree {
flex: 1;
min-width: 250px;
background: var(--vp-c-bg);
border-radius: 6px;
overflow: hidden;
}
.tree-header {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
background: var(--vp-c-bg-alt);
font-weight: bold;
font-size: 0.85rem;
}
.tree-content {
max-height: 280px;
overflow-y: auto;
}
.tree-item {
display: flex;
align-items: center;
gap: 0.25rem;
padding: 0.35rem 0.5rem;
cursor: pointer;
transition: all 0.2s;
font-size: 0.85rem;
}
.tree-item:hover {
background: var(--vp-c-bg-soft);
}
.tree-item.selected {
background: var(--vp-c-brand-soft);
}
.item-icon {
font-size: 0.9rem;
}
.fs-detail {
flex: 1;
min-width: 250px;
}
.detail-header {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
margin-bottom: 0.75rem;
}
.detail-icon {
font-size: 1.5rem;
}
.detail-name {
font-weight: bold;
font-size: 1rem;
}
.detail-info {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 4px;
margin-bottom: 0.75rem;
}
.info-row {
display: flex;
justify-content: space-between;
padding: 0.25rem 0;
font-size: 0.85rem;
border-bottom: 1px solid var(--vp-c-divider);
}
.info-row:last-child {
border-bottom: none;
}
.info-label {
color: var(--vp-c-text-2);
}
.info-value {
font-weight: 500;
}
.inode-info {
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
}
.inode-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.inode-visual {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.inode-block {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 4px;
}
.inode-label {
display: block;
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-bottom: 0.25rem;
}
.inode-value {
font-weight: bold;
font-size: 0.9rem;
}
.data-blocks {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.block {
padding: 0.15rem 0.4rem;
background: var(--vp-c-brand-soft);
border-radius: 3px;
font-size: 0.75rem;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,404 @@
<template>
<div class="language-map-demo">
<div class="demo-header">
<span class="icon">🗺</span>
<span class="title">编程语言图谱语言的演化</span>
<span class="subtitle">从机器语言到现代语言</span>
</div>
<div class="demo-content">
<div class="timeline">
<div class="timeline-item" v-for="(era, i) in eras" :key="i">
<div class="era-year">{{ era.year }}</div>
<div class="era-content">
<div class="era-name">{{ era.name }}</div>
<div class="era-langs">{{ era.languages.join(' → ') }}</div>
<div class="era-desc">{{ era.desc }}</div>
</div>
</div>
</div>
<div class="paradigm-section">
<div class="section-title">编程范式</div>
<div class="paradigm-tabs">
<button
v-for="p in paradigms"
:key="p.name"
:class="['tab-btn', { active: activeParadigm === p.name }]"
@click="activeParadigm = p.name"
>{{ p.name }}</button>
</div>
<div class="paradigm-content" v-if="currentParadigm">
<div class="paradigm-desc">{{ currentParadigm.desc }}</div>
<div class="paradigm-langs">
<span class="label">代表语言</span>
<span v-for="lang in currentParadigm.languages" :key="lang" class="lang-tag">{{ lang }}</span>
</div>
<div class="paradigm-example">
<div class="example-label">代码示例</div>
<pre><code>{{ currentParadigm.example }}</code></pre>
</div>
</div>
</div>
<div class="type-section">
<div class="section-title">类型系统分类</div>
<div class="type-grid">
<div class="type-card" v-for="t in typeCategories" :key="t.name">
<div class="card-header">
<span class="card-name">{{ t.name }}</span>
<span class="card-type">{{ t.type }}</span>
</div>
<div class="card-desc">{{ t.desc }}</div>
<div class="card-examples">{{ t.examples.join(', ') }}</div>
</div>
</div>
</div>
<div class="comparison-table">
<div class="table-title">语言特性对比</div>
<table>
<thead>
<tr>
<th>语言</th>
<th>类型</th>
<th>范式</th>
<th>运行方式</th>
<th>主要用途</th>
</tr>
</thead>
<tbody>
<tr v-for="lang in languageComparison" :key="lang.name">
<td class="lang-name">{{ lang.name }}</td>
<td>{{ lang.type }}</td>
<td>{{ lang.paradigm }}</td>
<td>{{ lang.runtime }}</td>
<td>{{ lang.usage }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>编程语言是人类与计算机沟通的桥梁不同的语言有不同的设计哲学适合解决不同类型的问题选择语言时要考虑问题领域团队熟悉度生态系统等因素
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const eras = [
{ year: '1950s', name: '早期语言', languages: ['Fortran', 'Lisp', 'COBOL'], desc: '科学计算和商业应用' },
{ year: '1960s', name: '结构化编程', languages: ['ALGOL', 'BASIC', 'PL/I'], desc: '引入结构化控制流' },
{ year: '1970s', name: '系统编程', languages: ['C', 'Pascal', 'Smalltalk'], desc: '面向对象和系统级开发' },
{ year: '1980s', name: '面向对象', languages: ['C++', 'Objective-C', 'Perl'], desc: 'OOP 成为主流' },
{ year: '1990s', name: '互联网时代', languages: ['Java', 'JavaScript', 'Python', 'PHP'], desc: 'Web 开发驱动语言发展' },
{ year: '2000s', name: '现代语言', languages: ['C#', 'Ruby', 'Scala', 'Go'], desc: '注重开发效率和安全性' },
{ year: '2010s', name: '新一代语言', languages: ['Rust', 'Swift', 'Kotlin', 'TypeScript'], desc: '内存安全与类型系统' }
]
const activeParadigm = ref('命令式')
const paradigms = [
{
name: '命令式',
desc: '通过语句改变程序状态,描述"怎么做"',
languages: ['C', 'Fortran', 'BASIC'],
example: `// 计算数组总和
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}`
},
{
name: '面向对象',
desc: '将数据和操作封装在对象中,模拟现实世界',
languages: ['Java', 'C++', 'Python', 'Ruby'],
example: `class Dog {
constructor(name) {
this.name = name
}
bark() {
console.log(this.name + ' says woof!')
}
}`
},
{
name: '函数式',
desc: '将计算视为函数求值,避免状态变化',
languages: ['Haskell', 'Lisp', 'Erlang', 'F#'],
example: `-- 计算数组总和
sum arr = foldl (+) 0 arr
-- 或更简洁
sum = foldl (+) 0`
},
{
name: '声明式',
desc: '描述"做什么"而非"怎么做"',
languages: ['SQL', 'Prolog', 'HTML'],
example: `-- 查询所有用户
SELECT name, email
FROM users
WHERE active = true
ORDER BY created_at DESC`
}
]
const currentParadigm = computed(() => {
return paradigms.find(p => p.name === activeParadigm.value)
})
const typeCategories = [
{ name: '静态类型', type: '编译时检查', desc: '变量类型在编译时确定', examples: ['Java', 'C++', 'Rust', 'TypeScript'] },
{ name: '动态类型', type: '运行时检查', desc: '变量类型在运行时确定', examples: ['Python', 'JavaScript', 'Ruby', 'PHP'] },
{ name: '强类型', type: '严格检查', desc: '不允许隐式类型转换', examples: ['Python', 'Java', 'Rust', 'Haskell'] },
{ name: '弱类型', type: '宽松检查', desc: '允许隐式类型转换', examples: ['JavaScript', 'PHP', 'C'] }
]
const languageComparison = [
{ name: 'Python', type: '动态强类型', paradigm: '多范式', runtime: '解释执行', usage: 'AI、数据分析、Web' },
{ name: 'JavaScript', type: '动态弱类型', paradigm: '多范式', runtime: 'JIT 编译', usage: 'Web 前端、Node.js' },
{ name: 'Java', type: '静态强类型', paradigm: '面向对象', runtime: 'JVM', usage: '企业应用、Android' },
{ name: 'C++', type: '静态弱类型', paradigm: '多范式', runtime: '编译执行', usage: '系统、游戏、嵌入式' },
{ name: 'Rust', type: '静态强类型', paradigm: '多范式', runtime: '编译执行', usage: '系统、WebAssembly' },
{ name: 'Go', type: '静态强类型', paradigm: '并发导向', runtime: '编译执行', usage: '云原生、微服务' }
]
</script>
<style scoped>
.language-map-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.timeline {
display: flex;
flex-direction: column;
gap: 0.5rem;
margin-bottom: 1rem;
}
.timeline-item {
display: flex;
gap: 0.75rem;
padding: 0.5rem;
background: var(--vp-c-bg);
border-radius: 6px;
}
.era-year {
font-weight: bold;
font-size: 0.85rem;
color: var(--vp-c-brand);
min-width: 60px;
}
.era-name {
font-weight: bold;
font-size: 0.85rem;
}
.era-langs {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.era-desc {
font-size: 0.75rem;
color: var(--vp-c-text-3);
}
.section-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.paradigm-section {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.paradigm-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 0.75rem;
flex-wrap: wrap;
}
.tab-btn {
padding: 0.35rem 0.6rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.paradigm-desc {
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.paradigm-langs {
display: flex;
align-items: center;
gap: 0.25rem;
flex-wrap: wrap;
margin-bottom: 0.5rem;
}
.label {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.lang-tag {
padding: 0.15rem 0.4rem;
background: var(--vp-c-brand-soft);
border-radius: 3px;
font-size: 0.75rem;
}
.paradigm-example {
background: var(--vp-c-bg-alt);
border-radius: 4px;
overflow: hidden;
}
.example-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
padding: 0.25rem 0.5rem;
background: var(--vp-c-divider);
}
pre {
margin: 0;
padding: 0.5rem;
font-size: 0.75rem;
overflow-x: auto;
}
code {
font-family: monospace;
}
.type-section {
margin-bottom: 1rem;
}
.type-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 0.5rem;
}
.type-card {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 6px;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.25rem;
}
.card-name {
font-weight: bold;
font-size: 0.85rem;
}
.card-type {
font-size: 0.7rem;
color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
padding: 0.1rem 0.3rem;
border-radius: 3px;
}
.card-desc {
font-size: 0.8rem;
color: var(--vp-c-text-2);
margin-bottom: 0.25rem;
}
.card-examples {
font-size: 0.75rem;
color: var(--vp-c-text-3);
}
.comparison-table {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.table-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.8rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.35rem;
text-align: left;
}
th {
background: var(--vp-c-bg);
}
.lang-name {
font-weight: bold;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,374 @@
<template>
<div class="logic-gate-demo">
<div class="demo-header">
<span class="icon">🔌</span>
<span class="title">逻辑门用开关做运算</span>
<span class="subtitle">晶体管组合成基本运算单元</span>
</div>
<div class="demo-content">
<div class="gate-tabs">
<button
v-for="gate in gates"
:key="gate.name"
:class="['tab-btn', { active: activeGate === gate.name }]"
@click="activeGate = gate.name"
>
{{ gate.name }}
</button>
</div>
<div class="gate-display">
<div class="gate-visual">
<div class="inputs">
<div class="input-item">
<span>A:</span>
<button
class="input-btn"
:class="{ on: inputA }"
@click="inputA = !inputA"
>{{ inputA ? '1' : '0' }}</button>
</div>
<div class="input-item">
<span>B:</span>
<button
class="input-btn"
:class="{ on: inputB }"
@click="inputB = !inputB"
>{{ inputB ? '1' : '0' }}</button>
</div>
</div>
<div class="gate-symbol">
<svg viewBox="0 0 120 80" class="gate-svg">
<template v-if="activeGate === 'AND'">
<path d="M20,20 L20,60 L60,60 Q90,60 90,40 Q90,20 60,20 Z" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="90" y1="40" x2="110" y2="40" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="30" x2="20" y2="30" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="50" x2="20" y2="50" stroke="var(--vp-c-brand)" stroke-width="2"/>
</template>
<template v-else-if="activeGate === 'OR'">
<path d="M20,20 Q40,40 20,60 Q60,60 90,40 Q60,20 20,20" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="90" y1="40" x2="110" y2="40" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="30" x2="25" y2="30" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="50" x2="25" y2="50" stroke="var(--vp-c-brand)" stroke-width="2"/>
</template>
<template v-else-if="activeGate === 'NOT'">
<polygon points="20,20 80,40 20,60" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<circle cx="85" cy="40" r="5" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="90" y1="40" x2="110" y2="40" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="40" x2="20" y2="40" stroke="var(--vp-c-brand)" stroke-width="2"/>
</template>
<template v-else-if="activeGate === 'XOR'">
<path d="M25,20 Q45,40 25,60 Q65,60 95,40 Q65,20 25,20" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<path d="M15,20 Q35,40 15,60" fill="none" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="95" y1="40" x2="115" y2="40" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="30" x2="30" y2="30" stroke="var(--vp-c-brand)" stroke-width="2"/>
<line x1="0" y1="50" x2="30" y2="50" stroke="var(--vp-c-brand)" stroke-width="2"/>
</template>
</svg>
<div class="gate-name">{{ activeGate }}</div>
</div>
<div class="output">
<span class="output-label">输出:</span>
<span class="output-value" :class="{ on: output }">{{ output ? '1' : '0' }}</span>
</div>
</div>
<div class="truth-table-mini">
<div class="table-title">{{ activeGate }} 真值表</div>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr v-for="row in currentTruthTable" :key="row.a + '-' + row.b"
:class="{ highlight: row.a === inputA && row.b === inputB && (activeGate !== 'NOT') }">
<td>{{ row.a }}</td>
<td>{{ row.b }}</td>
<td>{{ row.out }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="gate-explanation">
<div class="exp-title">{{ currentGate.expTitle }}</div>
<div class="exp-content">{{ currentGate.expContent }}</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>逻辑门用晶体管的"开关"组合实现基本运算AND门像"串联开关"(两个都开才通)OR门像"并联开关"(任一个开就通)
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeGate = ref('AND')
const inputA = ref(false)
const inputB = ref(false)
const gates = [
{
name: 'AND',
expTitle: 'AND门:两个都为1才输出1',
expContent: '就像串联的两个开关,必须两个都按下灯才会亮。用于"同时满足多个条件"的场景。'
},
{
name: 'OR',
expTitle: 'OR门:任一个为1就输出1',
expContent: '就像并联的两个开关,按任意一个灯就会亮。用于"满足任一条件"的场景。'
},
{
name: 'NOT',
expTitle: 'NOT门:取反,0变11变0',
expContent: '就像一个反相器,输入开就输出关,输入关就输出开。用于"否定"的场景。'
},
{
name: 'XOR',
expTitle: 'XOR门:相同为0,不同为1',
expContent: '就像"异或"判断,两个输入不同才输出1。用于比较两个值是否不同。'
}
]
const currentGate = computed(() => gates.find(g => g.name === activeGate.value))
const output = computed(() => {
const a = inputA.value
const b = inputB.value
switch (activeGate.value) {
case 'AND': return a && b ? 1 : 0
case 'OR': return a || b ? 1 : 0
case 'NOT': return a ? 0 : 1
case 'XOR': return a !== b ? 1 : 0
default: return 0
}
})
const currentTruthTable = computed(() => {
if (activeGate.value === 'NOT') {
return [
{ a: 0, b: '-', out: 1 },
{ a: 1, b: '-', out: 0 }
]
}
const table = []
for (let a = 0; a <= 1; a++) {
for (let b = 0; b <= 1; b++) {
let out = 0
switch (activeGate.value) {
case 'AND': out = a && b ? 1 : 0; break
case 'OR': out = a || b ? 1 : 0; break
case 'XOR': out = a !== b ? 1 : 0; break
}
table.push({ a, b, out })
}
}
return table
})
</script>
<style scoped>
.logic-gate-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.gate-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.tab-btn {
padding: 0.4rem 0.8rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
transition: all 0.2s;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.gate-display {
display: flex;
gap: 1.5rem;
align-items: flex-start;
flex-wrap: wrap;
}
.gate-visual {
display: flex;
align-items: center;
gap: 1rem;
}
.inputs {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.input-item {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
}
.input-btn {
width: 36px;
height: 36px;
border: 2px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
font-weight: bold;
transition: all 0.2s;
}
.input-btn.on {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.gate-symbol {
width: 120px;
text-align: center;
}
.gate-svg {
width: 100%;
height: 60px;
}
.gate-name {
font-weight: bold;
font-size: 0.9rem;
margin-top: 0.25rem;
color: var(--vp-c-brand);
}
.output {
display: flex;
align-items: center;
gap: 0.5rem;
}
.output-label {
font-size: 0.85rem;
}
.output-value {
width: 36px;
height: 36px;
display: flex;
align-items: center;
justify-content: center;
border: 2px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
font-weight: bold;
font-size: 1.1rem;
}
.output-value.on {
background: var(--vp-c-success);
color: white;
border-color: var(--vp-c-success);
}
.truth-table-mini {
flex: 1;
min-width: 150px;
}
.table-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.8rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.3rem 0.5rem;
text-align: center;
}
th {
background: var(--vp-c-bg-alt);
}
tr.highlight {
background: var(--vp-c-brand-soft);
}
.gate-explanation {
width: 100%;
margin-top: 1rem;
padding: 0.75rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
}
.exp-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.25rem;
}
.exp-content {
font-size: 0.85rem;
color: var(--vp-c-text-2);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,282 @@
<template>
<div class="memory-demo">
<div class="demo-header">
<span class="icon">🧠</span>
<span class="title">内存管理程序的"工作台"</span>
<span class="subtitle">操作系统如何分配和管理内存</span>
</div>
<div class="demo-content">
<div class="memory-visual">
<div class="mem-header">
<span>虚拟内存空间 (4GB)</span>
<span class="used-info">已用: {{ usedMemory }}MB / 4096MB</span>
</div>
<div class="mem-blocks">
<div
v-for="(block, i) in memoryBlocks"
:key="i"
class="mem-block"
:class="{ allocated: block.allocated, selected: selectedBlock === i }"
:style="{ height: block.size + '%' }"
@click="selectedBlock = i"
>
<span class="block-label" v-if="block.size > 5">{{ block.name }}</span>
<span class="block-size" v-if="block.size > 8">{{ block.sizeMB }}MB</span>
</div>
</div>
</div>
<div class="memory-info">
<div class="info-section">
<div class="section-title">内存分配策略</div>
<div class="strategy-tabs">
<button
v-for="s in strategies"
:key="s.name"
:class="['strat-btn', { active: activeStrategy === s.name }]"
@click="activeStrategy = s.name"
>{{ s.name }}</button>
</div>
<div class="strategy-desc">{{ currentStrategy.desc }}</div>
</div>
<div class="info-section">
<div class="section-title">虚拟内存的作用</div>
<div class="vm-benefits">
<div class="benefit-item" v-for="b in benefits" :key="b.title">
<span class="benefit-icon">{{ b.icon }}</span>
<div class="benefit-content">
<span class="benefit-title">{{ b.title }}</span>
<span class="benefit-desc">{{ b.desc }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>虚拟内存让每个进程都以为自己独占整个内存空间实际由操作系统统一管理和映射实现隔离和保护
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const selectedBlock = ref(0)
const activeStrategy = ref('首次适应')
const memoryBlocks = ref([
{ name: '内核空间', size: 25, allocated: true, sizeMB: 1024 },
{ name: '进程A', size: 15, allocated: true, sizeMB: 600 },
{ name: '空闲', size: 5, allocated: false, sizeMB: 200 },
{ name: '进程B', size: 20, allocated: true, sizeMB: 800 },
{ name: '空闲', size: 10, allocated: false, sizeMB: 400 },
{ name: '进程C', size: 10, allocated: true, sizeMB: 400 },
{ name: '空闲', size: 15, allocated: false, sizeMB: 600 }
])
const strategies = [
{ name: '首次适应', desc: '从内存开始找,找到第一个足够大的空闲块就分配。速度快,但可能产生小碎片。' },
{ name: '最佳适应', desc: '找最小的能满足需求的空闲块。内存利用率高,但可能产生很多小碎片。' },
{ name: '最坏适应', desc: '找最大的空闲块分配。减少小碎片,但大块内存很快用完。' }
]
const benefits = [
{ icon: '🔒', title: '内存隔离', desc: '进程间互不干扰,一个崩溃不影响其他' },
{ icon: '📦', title: '内存保护', desc: '防止进程访问不该访问的内存区域' },
{ icon: '💾', title: '内存扩展', desc: '用磁盘当内存用,突破物理内存限制' }
]
const currentStrategy = computed(() => {
return strategies.find(s => s.name === activeStrategy.value)
})
const usedMemory = computed(() => {
return memoryBlocks.value
.filter(b => b.allocated)
.reduce((sum, b) => sum + b.sizeMB, 0)
})
</script>
<style scoped>
.memory-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.memory-visual {
flex: 1;
min-width: 200px;
}
.mem-header {
display: flex;
justify-content: space-between;
font-size: 0.8rem;
margin-bottom: 0.5rem;
padding: 0.25rem 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
}
.used-info {
color: var(--vp-c-brand);
font-weight: bold;
}
.mem-blocks {
display: flex;
flex-direction: column;
gap: 2px;
height: 250px;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
overflow: hidden;
}
.mem-block {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.2s;
}
.mem-block.allocated {
background: var(--vp-c-brand-soft);
}
.mem-block:not(.allocated) {
background: var(--vp-c-bg);
border: 1px dashed var(--vp-c-divider);
}
.mem-block.selected {
outline: 2px solid var(--vp-c-brand);
}
.block-label {
font-size: 0.75rem;
font-weight: bold;
}
.block-size {
font-size: 0.65rem;
color: var(--vp-c-text-2);
}
.memory-info {
flex: 1;
min-width: 280px;
}
.info-section {
margin-bottom: 1rem;
}
.section-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.strategy-tabs {
display: flex;
gap: 0.25rem;
margin-bottom: 0.5rem;
}
.strat-btn {
padding: 0.25rem 0.5rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
font-size: 0.75rem;
cursor: pointer;
}
.strat-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.strategy-desc {
font-size: 0.8rem;
color: var(--vp-c-text-2);
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 4px;
}
.vm-benefits {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.benefit-item {
display: flex;
gap: 0.5rem;
padding: 0.5rem;
background: var(--vp-c-bg);
border-radius: 4px;
}
.benefit-icon {
font-size: 1.2rem;
}
.benefit-content {
display: flex;
flex-direction: column;
}
.benefit-title {
font-weight: bold;
font-size: 0.85rem;
}
.benefit-desc {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,361 @@
<template>
<div class="network-layers-demo">
<div class="demo-header">
<span class="icon">🌐</span>
<span class="title">网络五层模型</span>
<span class="subtitle">从应用到物理的数据封装过程</span>
</div>
<div class="demo-content">
<div class="layers-container">
<div
v-for="(layer, i) in layers"
:key="i"
:class="['layer', { active: activeLayer === i }]"
@click="activeLayer = i"
>
<div class="layer-num">{{ 5 - i }}</div>
<div class="layer-info">
<div class="layer-name">{{ layer.name }}</div>
<div class="layer-protocol">{{ layer.protocols }}</div>
</div>
<div class="layer-device" v-if="layer.device">{{ layer.device }}</div>
</div>
</div>
<div class="layer-detail" v-if="currentLayer">
<div class="detail-header">
<span class="detail-name">{{ currentLayer.name }}</span>
<span class="detail-analogy">{{ currentLayer.analogy }}</span>
</div>
<div class="detail-desc">{{ currentLayer.desc }}</div>
<div class="detail-tasks">
<div class="task-title">核心任务</div>
<ul>
<li v-for="(task, j) in currentLayer.tasks" :key="j">{{ task }}</li>
</ul>
</div>
<div class="detail-unit">
<span class="label">数据单位</span>
<span class="value">{{ currentLayer.unit }}</span>
</div>
</div>
<div class="encapsulation-demo">
<div class="encap-title">数据封装过程</div>
<div class="encap-flow">
<div class="encap-step" v-for="(step, i) in encapsulation" :key="i">
<div class="step-layer">{{ step.layer }}</div>
<div class="step-data">
<span class="header" v-if="step.header">{{ step.header }}</span>
<span class="payload">{{ step.payload }}</span>
</div>
</div>
<div class="arrow"> 发送</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>分层设计让网络协议模块化每层只关心自己的职责数据从应用层向下传递时每层都会添加自己的"信封"(头部)接收时再逐层拆开
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeLayer = ref(0)
const layers = [
{
name: '应用层',
protocols: 'HTTP, FTP, SMTP, DNS',
device: '',
analogy: '客户服务部门',
desc: '直接为用户的应用程序提供服务,处理具体的业务逻辑。',
tasks: ['定义应用程序之间的通信格式', '处理用户身份认证', '数据格式转换'],
unit: '消息(Message)'
},
{
name: '传输层',
protocols: 'TCP, UDP',
device: '',
analogy: '包裹分拣组',
desc: '负责端到端的数据传输,确保数据的可靠性或实时性。',
tasks: ['建立和管理端到端连接', '分段和重组数据', '流量控制和拥塞控制', '端口寻址'],
unit: '段(Segment)'
},
{
name: '网络层',
protocols: 'IP, ICMP, ARP',
device: '路由器',
analogy: '路由规划部',
desc: '负责将数据包从源主机传送到目标主机,实现跨网络通信。',
tasks: ['IP地址分配和管理', '路由选择', '数据包转发', '拥塞控制'],
unit: '包(Packet)'
},
{
name: '数据链路层',
protocols: '以太网, Wi-Fi',
device: '交换机',
analogy: '车队管理',
desc: '负责在直连的两个节点之间传输数据帧。',
tasks: ['MAC地址寻址', '帧的封装和解封装', '错误检测', '介质访问控制'],
unit: '帧(Frame)'
},
{
name: '物理层',
protocols: 'RS-232, RJ45',
device: '中继器, 集线器',
analogy: '道路和车辆',
desc: '负责在物理介质上传输原始的比特流。',
tasks: ['定义物理设备标准', '规定传输介质', '确定电气特性', '比特同步'],
unit: '比特(Bit)'
}
]
const currentLayer = computed(() => layers[activeLayer.value])
const encapsulation = [
{ layer: '应用层', header: '', payload: '原始数据' },
{ layer: '传输层', header: 'TCP头', payload: '原始数据' },
{ layer: '网络层', header: 'IP头', payload: 'TCP头+原始数据' },
{ layer: '数据链路层', header: 'MAC头', payload: 'IP头+TCP头+原始数据' },
{ layer: '物理层', header: '', payload: '比特流 010101...' }
]
</script>
<style scoped>
.network-layers-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1rem;
}
.layers-container {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.layer {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem;
background: var(--vp-c-bg);
border-radius: 6px;
cursor: pointer;
transition: all 0.2s;
border: 2px solid transparent;
}
.layer:hover {
background: var(--vp-c-bg-alt);
}
.layer.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.layer-num {
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-brand);
color: white;
border-radius: 50%;
font-size: 0.8rem;
font-weight: bold;
}
.layer-info {
flex: 1;
}
.layer-name {
font-weight: bold;
font-size: 0.85rem;
}
.layer-protocol {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.layer-device {
font-size: 0.7rem;
color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
padding: 0.15rem 0.4rem;
border-radius: 3px;
}
.layer-detail {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.5rem;
}
.detail-name {
font-weight: bold;
font-size: 1rem;
}
.detail-analogy {
font-size: 0.75rem;
color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
padding: 0.15rem 0.4rem;
border-radius: 3px;
}
.detail-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-bottom: 0.5rem;
}
.detail-tasks {
margin-bottom: 0.5rem;
}
.task-title {
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 0.25rem;
}
.detail-tasks ul {
margin: 0;
padding-left: 1rem;
font-size: 0.8rem;
}
.detail-tasks li {
margin: 0.15rem 0;
}
.detail-unit {
font-size: 0.8rem;
}
.detail-unit .label {
color: var(--vp-c-text-2);
}
.detail-unit .value {
font-weight: bold;
color: var(--vp-c-brand);
}
.encapsulation-demo {
grid-column: 1 / -1;
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.encap-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.encap-flow {
display: flex;
align-items: center;
gap: 0.5rem;
flex-wrap: wrap;
}
.encap-step {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.35rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
min-width: 80px;
}
.step-layer {
font-size: 0.7rem;
color: var(--vp-c-text-2);
}
.step-data {
display: flex;
gap: 0.15rem;
font-size: 0.75rem;
}
.header {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand);
padding: 0.1rem 0.3rem;
border-radius: 2px;
}
.payload {
background: var(--vp-c-divider);
padding: 0.1rem 0.3rem;
border-radius: 2px;
}
.arrow {
font-size: 0.8rem;
color: var(--vp-c-brand);
font-weight: bold;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
@media (max-width: 640px) {
.demo-content {
grid-template-columns: 1fr;
}
}
</style>
@@ -0,0 +1,261 @@
<template>
<div class="process-demo">
<div class="demo-header">
<span class="icon">🔄</span>
<span class="title">进程程序的"分身术"</span>
<span class="subtitle">一个程序如何同时运行多个实例</span>
</div>
<div class="demo-content">
<div class="process-list">
<div class="process-header">
<span class="col-name">进程名</span>
<span class="col-pid">PID</span>
<span class="col-state">状态</span>
<span class="col-mem">内存</span>
</div>
<div
v-for="p in processes"
:key="p.pid"
class="process-item"
:class="{ running: p.state === '运行中', selected: selectedPid === p.pid }"
@click="selectedPid = p.pid"
>
<span class="col-name">
<span class="process-icon">{{ p.icon }}</span>
{{ p.name }}
</span>
<span class="col-pid">{{ p.pid }}</span>
<span class="col-state">
<span class="state-badge" :class="p.state === '运行中' ? 'running' : 'waiting'">
{{ p.state }}
</span>
</span>
<span class="col-mem">{{ p.memory }}</span>
</div>
</div>
<div class="process-detail" v-if="selectedProcess">
<div class="detail-title">进程详情{{ selectedProcess.name }}</div>
<div class="detail-grid">
<div class="detail-item">
<span class="label">进程ID (PID)</span>
<span class="value">{{ selectedProcess.pid }}</span>
</div>
<div class="detail-item">
<span class="label">父进程ID</span>
<span class="value">{{ selectedProcess.ppid }}</span>
</div>
<div class="detail-item">
<span class="label">内存占用</span>
<span class="value">{{ selectedProcess.memory }}</span>
</div>
<div class="detail-item">
<span class="label">CPU 占用</span>
<span class="value">{{ selectedProcess.cpu }}%</span>
</div>
</div>
<div class="memory-layout">
<div class="layout-title">进程内存布局</div>
<div class="layout-visual">
<div class="segment" v-for="seg in memorySegments" :key="seg.name" :style="{ height: seg.height }">
<span class="seg-name">{{ seg.name }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>进程是程序的"运行实例"同一个程序可以启动多个进程每个进程有独立的内存空间互不干扰
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const selectedPid = ref(1001)
const processes = ref([
{ pid: 1001, name: 'Chrome', icon: '🌐', state: '运行中', memory: '512MB', cpu: 15, ppid: 1 },
{ pid: 1002, name: 'VS Code', icon: '📝', state: '运行中', memory: '384MB', cpu: 8, ppid: 1 },
{ pid: 1003, name: '微信', icon: '💬', state: '等待中', memory: '256MB', cpu: 2, ppid: 1 },
{ pid: 1004, name: '终端', icon: '⬛', state: '等待中', memory: '32MB', cpu: 0, ppid: 1002 },
{ pid: 1005, name: '音乐', icon: '🎵', state: '运行中', memory: '128MB', cpu: 3, ppid: 1 }
])
const selectedProcess = computed(() => {
return processes.value.find(p => p.pid === selectedPid.value)
})
const memorySegments = [
{ name: '栈区 (Stack)', height: '20%' },
{ name: '堆区 (Heap)', height: '35%' },
{ name: '数据段 (Data)', height: '15%' },
{ name: '代码段 (Text)', height: '30%' }
]
</script>
<style scoped>
.process-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.process-list {
flex: 1;
min-width: 280px;
font-size: 0.85rem;
}
.process-header {
display: grid;
grid-template-columns: 2fr 1fr 1.5fr 1fr;
gap: 0.5rem;
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
font-weight: bold;
margin-bottom: 0.25rem;
}
.process-item {
display: grid;
grid-template-columns: 2fr 1fr 1.5fr 1fr;
gap: 0.5rem;
padding: 0.5rem;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;
}
.process-item:hover {
background: var(--vp-c-bg);
}
.process-item.selected {
background: var(--vp-c-brand-soft);
}
.process-icon {
margin-right: 0.25rem;
}
.state-badge {
padding: 0.1rem 0.4rem;
border-radius: 3px;
font-size: 0.75rem;
}
.state-badge.running {
background: var(--vp-c-success);
color: white;
}
.state-badge.waiting {
background: var(--vp-c-divider);
color: var(--vp-c-text-2);
}
.process-detail {
flex: 1;
min-width: 250px;
}
.detail-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.detail-item {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 4px;
}
.detail-item .label {
display: block;
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.detail-item .value {
font-weight: bold;
font-size: 0.9rem;
}
.memory-layout {
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
}
.layout-title {
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.layout-visual {
display: flex;
flex-direction: column;
gap: 2px;
height: 120px;
}
.segment {
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-brand-soft);
border-radius: 2px;
}
.seg-name {
font-size: 0.7rem;
font-weight: bold;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,246 @@
<template>
<div class="storage-demo">
<div class="demo-header">
<span class="icon">💾</span>
<span class="title">存储层次从寄存器到云存储</span>
<span class="subtitle">速度与容量的权衡</span>
</div>
<div class="demo-content">
<div class="storage-pyramid">
<div
v-for="(level, i) in storageLevels"
:key="level.name"
class="level"
:class="{ active: activeLevel === i }"
:style="{ width: level.width }"
@click="activeLevel = i"
>
<div class="level-name">{{ level.name }}</div>
<div class="level-speed">{{ level.speed }}</div>
<div class="level-size">{{ level.size }}</div>
</div>
</div>
<div class="level-detail" v-if="currentLevel">
<div class="detail-title">{{ currentLevel.name }} 详情</div>
<div class="detail-grid">
<div class="detail-item">
<span class="label">访问速度</span>
<span class="value">{{ currentLevel.speed }}</span>
</div>
<div class="detail-item">
<span class="label">典型容量</span>
<span class="value">{{ currentLevel.size }}</span>
</div>
<div class="detail-item">
<span class="label">每字节成本</span>
<span class="value">{{ currentLevel.cost }}</span>
</div>
<div class="detail-item">
<span class="label">易失性</span>
<span class="value">{{ currentLevel.volatile }}</span>
</div>
</div>
<div class="detail-desc">{{ currentLevel.desc }}</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>存储遵循"金字塔"原则越快的存储越贵容量越小CPU 需要的数据放在最快的存储寄存器缓存暂时不用的放在慢速大容量存储磁盘云端
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeLevel = ref(0)
const storageLevels = [
{
name: '寄存器',
speed: '~1 纳秒',
size: '几百字节',
width: '30%',
cost: '极高',
volatile: '是',
desc: 'CPU 内部最快的存储,直接参与运算。数量有限,由编译器自动管理。'
},
{
name: 'L1 缓存',
speed: '~2 纳秒',
size: '32-64 KB',
width: '45%',
cost: '很高',
volatile: '是',
desc: 'CPU 内置的高速缓存,存储最常用的数据。每个核心独立拥有。'
},
{
name: 'L2/L3 缓存',
speed: '~10 纳秒',
size: '几 MB',
width: '60%',
cost: '高',
volatile: '是',
desc: '更大但稍慢的缓存,L3 通常多核心共享。'
},
{
name: '内存 (RAM)',
speed: '~100 纳秒',
size: '8-128 GB',
width: '75%',
cost: '中等',
volatile: '是',
desc: '程序运行时的主要工作区。断电后数据丢失。'
},
{
name: 'SSD 固态硬盘',
speed: '~100 微秒',
size: '256 GB - 4 TB',
width: '90%',
cost: '较低',
volatile: '否',
desc: '比机械硬盘快很多,无机械部件。断电数据保留。'
},
{
name: 'HDD 机械硬盘',
speed: '~10 毫秒',
size: '1-20 TB',
width: '100%',
cost: '低',
volatile: '否',
desc: '容量大、成本低,但有机械延迟。适合存储大量数据。'
}
]
const currentLevel = computed(() => storageLevels[activeLevel.value])
</script>
<style scoped>
.storage-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
gap: 1rem;
flex-wrap: wrap;
}
.storage-pyramid {
display: flex;
flex-direction: column;
align-items: center;
gap: 4px;
flex: 1;
min-width: 200px;
}
.level {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.5rem;
background: var(--vp-c-bg);
border: 1px solid var(--vp-c-divider);
cursor: pointer;
transition: all 0.2s;
}
.level:hover {
background: var(--vp-c-bg-soft);
}
.level.active {
background: var(--vp-c-brand-soft);
border-color: var(--vp-c-brand);
}
.level-name {
font-weight: bold;
font-size: 0.85rem;
}
.level-speed {
font-size: 0.75rem;
color: var(--vp-c-success);
}
.level-size {
font-size: 0.7rem;
color: var(--vp-c-text-2);
}
.level-detail {
flex: 1;
min-width: 250px;
}
.detail-title {
font-weight: bold;
font-size: 1rem;
margin-bottom: 0.75rem;
}
.detail-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.detail-item {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 4px;
}
.detail-item .label {
display: block;
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.detail-item .value {
font-weight: bold;
font-size: 0.9rem;
}
.detail-desc {
font-size: 0.85rem;
color: var(--vp-c-text-2);
background: var(--vp-c-bg-alt);
padding: 0.5rem;
border-radius: 4px;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,432 @@
<template>
<div class="subnet-calculator">
<div class="demo-header">
<span class="icon">🔢</span>
<span class="title">子网计算器</span>
<span class="subtitle">理解 IP 地址和子网掩码</span>
</div>
<div class="demo-content">
<div class="input-section">
<div class="input-group">
<label>IP 地址</label>
<div class="ip-inputs">
<input v-model="ip[0]" type="number" min="0" max="255" @input="calculate" />
<span>.</span>
<input v-model="ip[1]" type="number" min="0" max="255" @input="calculate" />
<span>.</span>
<input v-model="ip[2]" type="number" min="0" max="255" @input="calculate" />
<span>.</span>
<input v-model="ip[3]" type="number" min="0" max="255" @input="calculate" />
</div>
</div>
<div class="input-group">
<label>子网掩码 (CIDR)</label>
<div class="cidr-input">
<span>/</span>
<input v-model.number="cidr" type="number" min="8" max="30" @input="calculate" />
</div>
</div>
</div>
<div class="result-section">
<div class="result-item">
<span class="label">子网掩码</span>
<span class="value">{{ mask }}</span>
</div>
<div class="result-item">
<span class="label">网络地址</span>
<span class="value">{{ networkAddress }}</span>
</div>
<div class="result-item">
<span class="label">广播地址</span>
<span class="value">{{ broadcastAddress }}</span>
</div>
<div class="result-item">
<span class="label">可用主机数</span>
<span class="value">{{ usableHosts }}</span>
</div>
<div class="result-item">
<span class="label">主机范围</span>
<span class="value">{{ hostRange }}</span>
</div>
</div>
<div class="binary-section">
<div class="binary-title">二进制表示</div>
<div class="binary-row">
<span class="binary-label">IP 地址:</span>
<span class="binary-value">{{ ipBinary }}</span>
</div>
<div class="binary-row">
<span class="binary-label">子网掩码:</span>
<span class="binary-value">{{ maskBinary }}</span>
</div>
<div class="binary-row">
<span class="binary-label">网络部分:</span>
<span class="binary-value network">{{ networkBinary }}</span>
</div>
<div class="binary-row">
<span class="binary-label">主机部分:</span>
<span class="binary-value host">{{ hostBinary }}</span>
</div>
</div>
<div class="visual-section">
<div class="visual-title">地址结构可视化</div>
<div class="address-visual">
<div class="bit-blocks">
<div
v-for="(bit, i) in bits"
:key="i"
:class="['bit', { network: i < cidr, host: i >= cidr }]"
>
{{ bit }}
</div>
</div>
<div class="legend">
<span class="legend-item"><span class="network-box"></span> 网络位 ({{ cidr }})</span>
<span class="legend-item"><span class="host-box"></span> 主机位 ({{ 32 - cidr }})</span>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>子网掩码决定了 IP 地址的哪部分是"网络号"(小区)哪部分是"主机号"(房间)/24 表示前 24 位是网络位 8 位是主机位
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
const ip = ref([192, 168, 1, 100])
const cidr = ref(24)
const mask = computed(() => {
const maskValue = 0xFFFFFFFF << (32 - cidr.value)
return [
(maskValue >>> 24) & 255,
(maskValue >>> 16) & 255,
(maskValue >>> 8) & 255,
maskValue & 255
].join('.')
})
const ipValue = computed(() => {
return (parseInt(ip.value[0]) << 24) +
(parseInt(ip.value[1]) << 16) +
(parseInt(ip.value[2]) << 8) +
parseInt(ip.value[3])
})
const maskValue = computed(() => {
return 0xFFFFFFFF << (32 - cidr.value)
})
const networkAddress = computed(() => {
const network = ipValue.value & maskValue.value
return [
(network >>> 24) & 255,
(network >>> 16) & 255,
(network >>> 8) & 255,
network & 255
].join('.')
})
const broadcastAddress = computed(() => {
const network = ipValue.value & maskValue.value
const broadcast = network | (~maskValue.value >>> 0)
return [
(broadcast >>> 24) & 255,
(broadcast >>> 16) & 255,
(broadcast >>> 8) & 255,
broadcast & 255
].join('.')
})
const usableHosts = computed(() => {
return Math.pow(2, 32 - cidr.value) - 2
})
const hostRange = computed(() => {
const network = ipValue.value & maskValue.value
const first = network + 1
const last = (network | (~maskValue.value >>> 0)) - 1
const firstIP = [
(first >>> 24) & 255,
(first >>> 16) & 255,
(first >>> 8) & 255,
first & 255
].join('.')
const lastIP = [
(last >>> 24) & 255,
(last >>> 16) & 255,
(last >>> 8) & 255,
last & 255
].join('.')
return `${firstIP} - ${lastIP}`
})
const toBinary = (num) => {
return num.toString(2).padStart(8, '0')
}
const ipBinary = computed(() => {
return ip.value.map(toBinary).join(' ')
})
const maskBinary = computed(() => {
const m = [
(maskValue.value >>> 24) & 255,
(maskValue.value >>> 16) & 255,
(maskValue.value >>> 8) & 255,
maskValue.value & 255
]
return m.map(toBinary).join(' ')
})
const bits = computed(() => {
return ip.value.map(octet => toBinary(parseInt(octet))).join('').split('')
})
const networkBinary = computed(() => {
return bits.value.slice(0, cidr.value).join('') + ' '.repeat(32 - cidr.value)
})
const hostBinary = computed(() => {
return ' '.repeat(cidr.value) + bits.value.slice(cidr.value).join('')
})
const calculate = () => {
ip.value = ip.value.map(v => Math.min(255, Math.max(0, parseInt(v) || 0)))
cidr.value = Math.min(30, Math.max(8, cidr.value || 24))
}
onMounted(() => {
calculate()
})
</script>
<style scoped>
.subnet-calculator {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.input-section {
display: flex;
gap: 1rem;
margin-bottom: 1rem;
flex-wrap: wrap;
}
.input-group {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.input-group label {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.ip-inputs {
display: flex;
align-items: center;
gap: 0.25rem;
}
.ip-inputs input {
width: 50px;
padding: 0.35rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg);
text-align: center;
font-size: 0.85rem;
}
.ip-inputs span {
color: var(--vp-c-text-2);
}
.cidr-input {
display: flex;
align-items: center;
gap: 0.25rem;
}
.cidr-input input {
width: 50px;
padding: 0.35rem;
border: 1px solid var(--vp-c-divider);
border-radius: 4px;
background: var(--vp-c-bg);
text-align: center;
font-size: 0.85rem;
}
.result-section {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.5rem;
margin-bottom: 1rem;
}
.result-item {
background: var(--vp-c-bg);
padding: 0.5rem;
border-radius: 6px;
}
.result-item .label {
display: block;
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-bottom: 0.15rem;
}
.result-item .value {
font-size: 0.9rem;
font-weight: bold;
color: var(--vp-c-brand);
}
.binary-section {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.binary-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.binary-row {
display: flex;
gap: 0.5rem;
font-family: monospace;
font-size: 0.75rem;
margin-bottom: 0.25rem;
}
.binary-label {
color: var(--vp-c-text-2);
min-width: 80px;
}
.binary-value {
letter-spacing: 1px;
}
.binary-value.network {
color: var(--vp-c-brand);
}
.binary-value.host {
color: var(--vp-c-text-3);
}
.visual-section {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.visual-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.bit-blocks {
display: flex;
flex-wrap: wrap;
gap: 2px;
margin-bottom: 0.5rem;
}
.bit {
width: 12px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.65rem;
font-family: monospace;
border-radius: 2px;
}
.bit.network {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand);
}
.bit.host {
background: var(--vp-c-divider);
color: var(--vp-c-text-2);
}
.legend {
display: flex;
gap: 1rem;
font-size: 0.75rem;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.25rem;
}
.network-box, .host-box {
width: 12px;
height: 12px;
border-radius: 2px;
}
.network-box {
background: var(--vp-c-brand-soft);
}
.host-box {
background: var(--vp-c-divider);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,584 @@
<template>
<div class="tcp-udp-demo">
<div class="demo-header">
<span class="icon">📦</span>
<span class="title">TCP vs UDP可靠 vs 快速</span>
<span class="subtitle">两种不同的传输策略</span>
</div>
<div class="demo-content">
<div class="comparison-tabs">
<button
:class="['tab-btn', { active: activeTab === 'tcp' }]"
@click="activeTab = 'tcp'"
>
<span class="tab-icon">📨</span>
<span>TCP (可靠)</span>
</button>
<button
:class="['tab-btn', { active: activeTab === 'udp' }]"
@click="activeTab = 'udp'"
>
<span class="tab-icon">📮</span>
<span>UDP (快速)</span>
</button>
</div>
<div class="protocol-detail" v-if="currentProtocol">
<div class="detail-header">
<span class="detail-name">{{ currentProtocol.name }}</span>
<span class="detail-full">{{ currentProtocol.fullName }}</span>
</div>
<div class="feature-grid">
<div class="feature-item" v-for="(feature, i) in currentProtocol.features" :key="i">
<span class="feature-icon">{{ feature.icon }}</span>
<span class="feature-name">{{ feature.name }}</span>
<span class="feature-value">{{ feature.value }}</span>
</div>
</div>
<div class="mechanism-section">
<div class="mechanism-title">核心机制</div>
<div class="mechanism-list">
<div class="mechanism-item" v-for="(m, i) in currentProtocol.mechanisms" :key="i">
<span class="mechanism-name">{{ m.name }}</span>
<span class="mechanism-desc">{{ m.desc }}</span>
</div>
</div>
</div>
<div class="use-cases">
<div class="use-title">适用场景</div>
<div class="use-tags">
<span class="use-tag" v-for="(use, i) in currentProtocol.useCases" :key="i">{{ use }}</span>
</div>
</div>
</div>
<div class="visual-demo">
<div class="visual-title">传输过程演示</div>
<div class="transmission-demo">
<div class="sender">
<div class="node-label">发送方</div>
<div class="packets">
<div
v-for="(packet, i) in packets"
:key="i"
:class="['packet', { sent: packet.sent, acked: packet.acked, lost: packet.lost }]"
>
{{ packet.seq }}
</div>
</div>
</div>
<div class="network-channel">
<div class="channel-label">网络通道</div>
<div class="channel-status" :class="{ congested: isCongested }">
{{ isCongested ? '拥堵' : '正常' }}
</div>
<button class="demo-btn" @click="runDemo">开始演示</button>
<button class="demo-btn" @click="toggleCongestion">{{ isCongested ? '恢复网络' : '模拟丢包' }}</button>
</div>
<div class="receiver">
<div class="node-label">接收方</div>
<div class="received-packets">
<div
v-for="(packet, i) in receivedPackets"
:key="i"
class="received-packet"
>
{{ packet }}
</div>
</div>
</div>
</div>
<div class="demo-log">
<div class="log-title">传输日志</div>
<div class="log-content">
<div v-for="(log, i) in logs" :key="i" class="log-item">{{ log }}</div>
</div>
</div>
</div>
<div class="comparison-table">
<div class="table-title">特性对比</div>
<table>
<thead>
<tr>
<th>特性</th>
<th>TCP</th>
<th>UDP</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, i) in comparisonData" :key="i">
<td class="feature-col">{{ row.feature }}</td>
<td :class="{ highlight: row.tcpBetter }">{{ row.tcp }}</td>
<td :class="{ highlight: !row.tcpBetter }">{{ row.udp }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>TCP 像挂号信确保送达但较慢UDP 像平信快速但不保证送达选择哪种协议取决于应用场景需要可靠性选 TCP需要实时性选 UDP
</div>
</div>
</template>
<script setup>
import { ref, computed, reactive } from 'vue'
const activeTab = ref('tcp')
const protocols = {
tcp: {
name: 'TCP',
fullName: 'Transmission Control Protocol',
features: [
{ icon: '✅', name: '可靠性', value: '保证数据送达' },
{ icon: '📊', name: '有序性', value: '按顺序重组' },
{ icon: '🔄', name: '重传机制', value: '丢包自动重传' },
{ icon: '⚖️', name: '流量控制', value: '防止接收方溢出' },
{ icon: '🚦', name: '拥塞控制', value: '避免网络拥堵' },
{ icon: '🤝', name: '连接导向', value: '需要建立连接' }
],
mechanisms: [
{ name: '三次握手', desc: '建立可靠连接,确保双方都能收发' },
{ name: '序列号', desc: '每个字节编号,保证有序和完整性' },
{ name: '确认应答', desc: '收到数据必须回复 ACK' },
{ name: '超时重传', desc: '未收到 ACK 则重传' },
{ name: '滑动窗口', desc: '控制发送速率,提高效率' }
],
useCases: ['网页浏览', '文件传输', '邮件发送', '数据库连接']
},
udp: {
name: 'UDP',
fullName: 'User Datagram Protocol',
features: [
{ icon: '⚡', name: '速度', value: '无连接开销' },
{ icon: '📦', name: '数据报', value: '独立的数据包' },
{ icon: '❌', name: '无保证', value: '不保证送达' },
{ icon: '🔀', name: '无序', value: '可能乱序到达' },
{ icon: '💡', name: '轻量', value: '头部仅 8 字节' },
{ icon: '🎯', name: '灵活', value: '应用层控制' }
],
mechanisms: [
{ name: '无连接', desc: '直接发送,无需建立连接' },
{ name: '校验和', desc: '检测数据是否损坏' },
{ name: '端口复用', desc: '支持多路复用' },
{ name: '应用层控制', desc: '由应用决定重传等策略' }
],
useCases: ['视频直播', '在线游戏', 'DNS 查询', 'VoIP 通话']
}
}
const currentProtocol = computed(() => protocols[activeTab.value])
const comparisonData = [
{ feature: '连接', tcp: '面向连接', udp: '无连接', tcpBetter: true },
{ feature: '可靠性', tcp: '可靠传输', udp: '不保证', tcpBetter: true },
{ feature: '顺序', tcp: '有序', udp: '可能乱序', tcpBetter: true },
{ feature: '速度', tcp: '较慢', udp: '快', tcpBetter: false },
{ feature: '头部开销', tcp: '20 字节', udp: '8 字节', tcpBetter: false },
{ feature: '流量控制', tcp: '有', udp: '无', tcpBetter: true },
{ feature: '拥塞控制', tcp: '有', udp: '无', tcpBetter: true },
{ feature: '广播/多播', tcp: '不支持', udp: '支持', tcpBetter: false }
]
const packets = ref([
{ seq: 1, sent: false, acked: false, lost: false },
{ seq: 2, sent: false, acked: false, lost: false },
{ seq: 3, sent: false, acked: false, lost: false },
{ seq: 4, sent: false, acked: false, lost: false }
])
const receivedPackets = ref([])
const logs = ref([])
const isCongested = ref(false)
const toggleCongestion = () => {
isCongested.value = !isCongested.value
logs.value.push(`网络状态: ${isCongested.value ? '拥堵(模拟丢包)' : '正常'}`)
}
const runDemo = async () => {
receivedPackets.value = []
logs.value = ['开始传输演示...']
for (let i = 0; i < packets.value.length; i++) {
packets.value[i].sent = false
packets.value[i].acked = false
packets.value[i].lost = false
}
const isTcp = activeTab.value === 'tcp'
for (let i = 0; i < packets.value.length; i++) {
const packet = packets.value[i]
packet.sent = true
if (isCongested.value && Math.random() > 0.5) {
packet.lost = true
logs.value.push(`${packet.seq} 丢失!`)
if (isTcp) {
await new Promise(r => setTimeout(r, 500))
logs.value.push(`TCP 重传包 ${packet.seq}...`)
packet.lost = false
receivedPackets.value.push(packet.seq)
packet.acked = true
logs.value.push(`${packet.seq} 重传成功`)
}
} else {
receivedPackets.value.push(packet.seq)
packet.acked = true
logs.value.push(`${packet.seq} 送达`)
}
await new Promise(r => setTimeout(r, 300))
}
if (isTcp) {
logs.value.push(`TCP 完成: 收到 ${receivedPackets.value.length} 个包,顺序: ${receivedPackets.value.join(', ')}`)
} else {
logs.value.push(`UDP 完成: 收到 ${receivedPackets.value.length} 个包`)
}
}
</script>
<style scoped>
.tcp-udp-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.comparison-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 1rem;
}
.tab-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.5rem;
border: 2px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
}
.tab-btn.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.tab-icon { font-size: 1.1rem; }
.protocol-detail {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.detail-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 0.75rem;
}
.detail-name {
font-weight: bold;
font-size: 1.1rem;
}
.detail-full {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.feature-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.feature-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.4rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
}
.feature-icon { font-size: 1rem; }
.feature-name { font-size: 0.75rem; color: var(--vp-c-text-2); }
.feature-value { font-size: 0.8rem; font-weight: bold; }
.mechanism-section {
margin-bottom: 0.75rem;
}
.mechanism-title, .use-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.mechanism-list {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.mechanism-item {
display: flex;
gap: 0.5rem;
font-size: 0.8rem;
}
.mechanism-name {
font-weight: bold;
color: var(--vp-c-brand);
min-width: 70px;
}
.mechanism-desc {
color: var(--vp-c-text-2);
}
.use-tags {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.use-tag {
padding: 0.2rem 0.5rem;
background: var(--vp-c-brand-soft);
border-radius: 4px;
font-size: 0.75rem;
}
.visual-demo {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.visual-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
.transmission-demo {
display: flex;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.sender, .receiver {
flex: 1;
padding: 0.5rem;
background: var(--vp-c-bg-alt);
border-radius: 6px;
}
.node-label {
font-size: 0.8rem;
font-weight: bold;
margin-bottom: 0.25rem;
}
.packets, .received-packets {
display: flex;
gap: 0.25rem;
flex-wrap: wrap;
}
.packet {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-divider);
border-radius: 4px;
font-size: 0.8rem;
font-weight: bold;
}
.packet.sent {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand);
}
.packet.acked {
background: var(--vp-c-brand);
color: white;
}
.packet.lost {
background: #ff6b6b;
color: white;
}
.received-packet {
width: 30px;
height: 30px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-brand);
color: white;
border-radius: 4px;
font-size: 0.8rem;
font-weight: bold;
}
.network-channel {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.25rem;
padding: 0.5rem;
}
.channel-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.channel-status {
font-size: 0.7rem;
padding: 0.15rem 0.4rem;
background: #51cf66;
color: white;
border-radius: 3px;
}
.channel-status.congested {
background: #ff6b6b;
}
.demo-btn {
padding: 0.25rem 0.5rem;
font-size: 0.7rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg);
border-radius: 4px;
cursor: pointer;
}
.demo-btn:hover {
background: var(--vp-c-bg-alt);
}
.demo-log {
background: var(--vp-c-bg-alt);
border-radius: 4px;
overflow: hidden;
}
.log-title {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
background: var(--vp-c-divider);
}
.log-content {
padding: 0.5rem;
max-height: 100px;
overflow-y: auto;
}
.log-item {
font-size: 0.75rem;
font-family: monospace;
margin-bottom: 0.15rem;
}
.comparison-table {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.table-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.8rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.4rem;
text-align: center;
}
th {
background: var(--vp-c-bg);
}
.feature-col {
text-align: left;
font-weight: bold;
}
.highlight {
background: var(--vp-c-brand-soft);
color: var(--vp-c-brand);
font-weight: bold;
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,201 @@
<template>
<div class="transistor-demo">
<div class="demo-header">
<span class="icon"></span>
<span class="title">晶体管数字世界的开关</span>
<span class="subtitle">一个开关如何变成计算能力</span>
</div>
<div class="demo-content">
<div class="switch-container">
<div class="switch-area" @click="toggleSwitch">
<div class="transistor-symbol">
<svg viewBox="0 0 100 80" class="transistor-svg">
<line x1="10" y1="40" x2="35" y2="40" stroke="var(--vp-c-text-1)" stroke-width="2"/>
<line x1="65" y1="40" x2="90" y2="40" stroke="var(--vp-c-text-1)" stroke-width="2"/>
<line x1="50" y1="20" x2="50" y2="35" stroke="var(--vp-c-text-1)" stroke-width="2"/>
<line x1="50" y1="45" x2="50" y2="60" stroke="var(--vp-c-text-1)" stroke-width="2"/>
<line x1="35" y1="30" x2="35" y2="50" stroke="var(--vp-c-text-1)" stroke-width="3"/>
<line x1="65" y1="30" x2="65" y2="50" stroke="var(--vp-c-text-1)" stroke-width="3"/>
<line x1="35" y1="40" x2="65" y2="40" stroke="var(--vp-c-text-1)" stroke-width="2"/>
<circle cx="50" cy="60" r="4" fill="var(--vp-c-text-1)"/>
</svg>
</div>
<div class="switch-label">
<span class="state-label">{{ isOn ? 'ON (1)' : 'OFF (0)' }}</span>
<div class="current-flow" :class="{ active: isOn }">
<span class="flow-indicator">电流</span>
</div>
</div>
</div>
</div>
<div class="truth-table">
<div class="table-title">晶体管状态表</div>
<table>
<thead>
<tr>
<th>栅极(控制端)</th>
<th>源极漏极</th>
<th>输出</th>
</tr>
</thead>
<tbody>
<tr :class="{ highlight: !isOn }">
<td>低电压 (0)</td>
<td>断开</td>
<td>0</td>
</tr>
<tr :class="{ highlight: isOn }">
<td>高电压 (1)</td>
<td>导通</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>晶体管就是一个用电控制的开关给它高电压(1)它就导通给低电压(0)它就断开这是所有数字计算的基础
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const isOn = ref(false)
const toggleSwitch = () => {
isOn.value = !isOn.value
}
</script>
<style scoped>
.transistor-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
gap: 1.5rem;
align-items: center;
flex-wrap: wrap;
}
.switch-container {
flex: 1;
min-width: 200px;
}
.switch-area {
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 8px;
padding: 1rem;
cursor: pointer;
transition: all 0.3s;
text-align: center;
}
.switch-area:hover {
border-color: var(--vp-c-brand);
}
.transistor-symbol {
width: 120px;
height: 80px;
margin: 0 auto 0.5rem;
}
.transistor-svg {
width: 100%;
height: 100%;
}
.switch-label {
display: flex;
flex-direction: column;
gap: 0.25rem;
align-items: center;
}
.state-label {
font-weight: bold;
font-size: 1.1rem;
color: var(--vp-c-brand);
}
.current-flow {
font-size: 0.8rem;
color: var(--vp-c-text-3);
opacity: 0.5;
transition: all 0.3s;
}
.current-flow.active {
opacity: 1;
color: var(--vp-c-success);
}
.truth-table {
flex: 1;
min-width: 250px;
}
.table-title {
font-weight: bold;
margin-bottom: 0.5rem;
font-size: 0.9rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.85rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.5rem;
text-align: center;
}
th {
background: var(--vp-c-bg-alt);
}
tr.highlight {
background: var(--vp-c-brand-soft);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,345 @@
<template>
<div class="transmission-demo">
<div class="demo-header">
<span class="icon">📡</span>
<span class="title">数据传输从串行到并行</span>
<span class="subtitle">数据如何在不同设备间移动</span>
</div>
<div class="demo-content">
<div class="transmission-types">
<div class="type-card" :class="{ active: activeType === 'serial' }" @click="activeType = 'serial'">
<div class="card-icon"></div>
<div class="card-title">串行传输</div>
<div class="card-desc">一位一位依次传输</div>
<div class="card-examples">USBSATAPCIe</div>
</div>
<div class="type-card" :class="{ active: activeType === 'parallel' }" @click="activeType = 'parallel'">
<div class="card-icon"></div>
<div class="card-title">并行传输</div>
<div class="card-desc">多位同时传输</div>
<div class="card-examples">旧式打印机接口IDE</div>
</div>
</div>
<div class="transmission-visual">
<div class="visual-title">{{ activeType === 'serial' ? '串行传输示意' : '并行传输示意' }}</div>
<div class="visual-area">
<div class="sender">
<div class="device-label">发送端</div>
<div class="data-bits">
<span v-for="(bit, i) in dataBits" :key="i" class="bit" :class="{ sending: sendingBit === i && activeType === 'serial' }">{{ bit }}</span>
</div>
</div>
<div class="channels">
<div v-if="activeType === 'serial'" class="channel serial">
<div class="channel-label">单通道</div>
<div class="channel-flow">
<span v-for="i in 5" :key="i" class="flow-dot" :class="{ active: sendingBit !== null }"></span>
</div>
</div>
<div v-else class="channel parallel">
<div v-for="i in 4" :key="i" class="channel-row">
<div class="channel-label">通道{{ i }}</div>
<div class="channel-flow">
<span class="flow-dot active"></span>
</div>
</div>
</div>
</div>
<div class="receiver">
<div class="device-label">接收端</div>
<div class="data-bits received">
<span v-for="(bit, i) in receivedBits" :key="i" class="bit">{{ bit }}</span>
</div>
</div>
</div>
<button class="send-btn" @click="startTransmission">发送数据</button>
</div>
<div class="comparison-table">
<div class="table-title">串行 vs 并行对比</div>
<table>
<thead>
<tr>
<th>特性</th>
<th>串行</th>
<th>并行</th>
</tr>
</thead>
<tbody>
<tr>
<td>传输线数量</td>
<td>1-几根</td>
<td>8-64</td>
</tr>
<tr>
<td>抗干扰能力</td>
<td></td>
<td>线间干扰</td>
</tr>
<tr>
<td>传输距离</td>
<td></td>
<td></td>
</tr>
<tr>
<td>现代应用</td>
<td>主流USBPCIe</td>
<td>较少</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>现代高速传输多采用串行方式虽然并行"看起来"更快一次传多位但串行可以跑更高频率抗干扰更强实际速度反而更快
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeType = ref('serial')
const dataBits = ref(['1', '0', '1', '1', '0', '0', '1', '0'])
const receivedBits = ref(['-', '-', '-', '-', '-', '-', '-', '-'])
const sendingBit = ref(null)
const startTransmission = () => {
if (activeType.value === 'serial') {
receivedBits.value = ['-', '-', '-', '-', '-', '-', '-', '-']
let i = 0
const interval = setInterval(() => {
if (i < dataBits.value.length) {
sendingBit.value = i
receivedBits.value[i] = dataBits.value[i]
i++
} else {
clearInterval(interval)
sendingBit.value = null
}
}, 300)
} else {
receivedBits.value = [...dataBits.value]
}
}
</script>
<style scoped>
.transmission-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.demo-content {
display: flex;
flex-direction: column;
gap: 1rem;
}
.transmission-types {
display: flex;
gap: 1rem;
}
.type-card {
flex: 1;
padding: 0.75rem;
background: var(--vp-c-bg);
border: 2px solid var(--vp-c-divider);
border-radius: 6px;
cursor: pointer;
text-align: center;
transition: all 0.2s;
}
.type-card.active {
border-color: var(--vp-c-brand);
background: var(--vp-c-brand-soft);
}
.card-icon {
font-size: 1.5rem;
margin-bottom: 0.25rem;
}
.card-title {
font-weight: bold;
font-size: 0.9rem;
}
.card-desc {
font-size: 0.8rem;
color: var(--vp-c-text-2);
}
.card-examples {
font-size: 0.75rem;
color: var(--vp-c-brand);
margin-top: 0.25rem;
}
.transmission-visual {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.visual-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
text-align: center;
}
.visual-area {
display: flex;
align-items: center;
justify-content: space-between;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.sender, .receiver {
text-align: center;
}
.device-label {
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-bottom: 0.25rem;
}
.data-bits {
display: flex;
gap: 2px;
}
.bit {
width: 20px;
height: 20px;
display: flex;
align-items: center;
justify-content: center;
background: var(--vp-c-bg-alt);
border-radius: 2px;
font-size: 0.75rem;
font-family: monospace;
}
.bit.sending {
background: var(--vp-c-brand);
color: white;
}
.channels {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.channel.serial {
display: flex;
flex-direction: column;
align-items: center;
}
.channel.parallel {
gap: 2px;
}
.channel-row {
display: flex;
align-items: center;
gap: 0.25rem;
}
.channel-label {
font-size: 0.65rem;
color: var(--vp-c-text-3);
}
.channel-flow {
display: flex;
gap: 2px;
}
.flow-dot {
font-size: 0.5rem;
color: var(--vp-c-divider);
}
.flow-dot.active {
color: var(--vp-c-brand);
}
.send-btn {
width: 100%;
padding: 0.5rem;
background: var(--vp-c-brand);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.85rem;
}
.comparison-table {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
}
.table-title {
font-weight: bold;
font-size: 0.85rem;
margin-bottom: 0.5rem;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 0.8rem;
}
th, td {
border: 1px solid var(--vp-c-divider);
padding: 0.4rem;
text-align: center;
}
th {
background: var(--vp-c-bg);
}
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
</style>
@@ -0,0 +1,481 @@
<template>
<div class="type-system-demo">
<div class="demo-header">
<span class="icon">🏷</span>
<span class="title">类型系统数据的分类规则</span>
<span class="subtitle">静态 vs 动态强类型 vs 弱类型</span>
</div>
<div class="demo-content">
<div class="type-quadrant">
<div class="quadrant-title">类型系统四象限</div>
<div class="quadrant-grid">
<div class="quadrant-cell strong-static">
<div class="cell-label">强类型 + 静态</div>
<div class="cell-langs">Java, Rust, Haskell</div>
<div class="cell-desc">最安全编译期检查</div>
</div>
<div class="quadrant-cell weak-static">
<div class="cell-label">弱类型 + 静态</div>
<div class="cell-langs">C, C++</div>
<div class="cell-desc">高效但需小心</div>
</div>
<div class="quadrant-cell strong-dynamic">
<div class="cell-label">强类型 + 动态</div>
<div class="cell-langs">Python, Ruby</div>
<div class="cell-desc">灵活运行时检查</div>
</div>
<div class="quadrant-cell weak-dynamic">
<div class="cell-label">弱类型 + 动态</div>
<div class="cell-langs">JavaScript, PHP</div>
<div class="cell-desc">最灵活但易出错</div>
</div>
</div>
<div class="axis-labels">
<span class="axis-x">静态 动态</span>
<span class="axis-y">强类型 弱类型</span>
</div>
</div>
<div class="type-demo">
<div class="demo-title">类型检查演示</div>
<div class="code-comparison">
<div class="code-block">
<div class="code-label">静态类型 (Java)</div>
<pre><code>String name = "Alice";
name = 123; // ❌ 编译错误
int x = 10;
String s = x; // ❌ 编译错误</code></pre>
<div class="code-result error">编译期发现错误</div>
</div>
<div class="code-block">
<div class="code-label">动态类型 (Python)</div>
<pre><code>name = "Alice"
name = 123 # 运行正常
x = 10
s = str(x) # 需要显式转换</code></pre>
<div class="code-result success">运行时类型可变</div>
</div>
</div>
</div>
<div class="conversion-demo">
<div class="demo-title">类型转换演示</div>
<div class="conversion-tabs">
<button
v-for="lang in languages"
:key="lang.name"
:class="['tab-btn', { active: activeLang === lang.name }]"
@click="activeLang = lang.name"
>{{ lang.name }}</button>
</div>
<div class="conversion-content" v-if="currentLang">
<div class="conversion-item" v-for="(item, i) in currentLang.conversions" :key="i">
<code class="code-expr">{{ item.expr }}</code>
<span class="arrow"></span>
<code class="code-result" :class="{ error: item.error }">{{ item.result }}</code>
<span class="explanation">{{ item.explain }}</span>
</div>
</div>
</div>
<div class="type-inference">
<div class="demo-title">类型推断</div>
<div class="inference-examples">
<div class="inference-item" v-for="(example, i) in inferenceExamples" :key="i">
<div class="inference-lang">{{ example.lang }}</div>
<code class="inference-code">{{ example.code }}</code>
<div class="inference-result">推断为: <span class="type">{{ example.type }}</span></div>
</div>
</div>
</div>
<div class="type-benefits">
<div class="benefits-title">类型系统的好处</div>
<div class="benefits-grid">
<div class="benefit-item" v-for="(b, i) in benefits" :key="i">
<span class="benefit-icon">{{ b.icon }}</span>
<span class="benefit-name">{{ b.name }}</span>
<span class="benefit-desc">{{ b.desc }}</span>
</div>
</div>
</div>
</div>
<div class="info-box">
<span class="icon">💡</span>
<strong>核心思想</strong>类型系统是编程语言的"交通规则"帮助我们在编译期或运行时发现错误静态类型在编译期检查动态类型在运行时检查强类型不允许隐式转换弱类型允许
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const activeLang = ref('JavaScript')
const languages = [
{
name: 'JavaScript',
conversions: [
{ expr: '"1" + 1', result: '"11"', explain: '字符串拼接', error: false },
{ expr: '"1" - 1', result: '0', explain: '自动转数字', error: false },
{ expr: '[] + []', result: '""', explain: '空数组转空字符串', error: false },
{ expr: '[] + {}', result: '"[object Object]"', explain: '对象转字符串', error: false },
{ expr: 'true + true', result: '2', explain: '布尔转数字', error: false }
]
},
{
name: 'Python',
conversions: [
{ expr: '"1" + 1', result: 'TypeError', explain: '不允许隐式转换', error: true },
{ expr: '"1" + str(1)', result: '"11"', explain: '显式转换', error: false },
{ expr: 'int("1") + 1', result: '2', explain: '显式转换', error: false },
{ expr: 'True + True', result: '2', explain: '布尔是整数子类', error: false },
{ expr: '[1] + [2]', result: '[1, 2]', explain: '列表拼接', error: false }
]
},
{
name: 'Java',
conversions: [
{ expr: '"1" + 1', result: '"11"', explain: '字符串拼接(特殊规则)', error: false },
{ expr: '(String) 1', result: '编译错误', explain: '不允许转换', error: true },
{ expr: '(int) 1.5', result: '1', explain: '强制类型转换', error: false },
{ expr: 'Integer.parseInt("1")', result: '1', explain: '显式解析', error: false }
]
},
{
name: 'Rust',
conversions: [
{ expr: '"1".to_string() + "1"', result: '"11"', explain: '字符串拼接', error: false },
{ expr: '"1".parse::<i32>()', result: 'Ok(1)', explain: '显式解析', error: false },
{ expr: '1_i32 + 1_i64', result: '编译错误', explain: '类型不匹配', error: true },
{ expr: '1 as f64', result: '1.0', explain: '显式转换', error: false }
]
}
]
const currentLang = computed(() => {
return languages.find(l => l.name === activeLang.value)
})
const inferenceExamples = [
{ lang: 'TypeScript', code: 'let x = 1', type: 'number' },
{ lang: 'TypeScript', code: 'let arr = [1, 2, 3]', type: 'number[]' },
{ lang: 'Rust', code: 'let x = 1', type: 'i32 (默认整数类型)' },
{ lang: 'Rust', code: 'let s = "hello"', type: '&str (字符串切片)' },
{ lang: 'Haskell', code: 'x = 1', type: 'Num a => a (多态)' },
{ lang: 'C++ (auto)', code: 'auto x = 1', type: 'int' }
]
const benefits = [
{ icon: '🐛', name: '错误检测', desc: '在编译期发现类型错误' },
{ icon: '📖', name: '文档作用', desc: '类型签名即文档' },
{ icon: '🔧', name: 'IDE 支持', desc: '自动补全、重构' },
{ icon: '⚡', name: '性能优化', desc: '编译器可进行优化' },
{ icon: '🧩', name: '代码抽象', desc: '类型作为设计工具' },
{ icon: '🔒', name: '安全保障', desc: '避免运行时类型错误' }
]
</script>
<style scoped>
.type-system-demo {
border: 1px solid var(--vp-c-divider);
border-radius: 8px;
background: var(--vp-c-bg-soft);
padding: 1rem;
margin: 1rem 0;
}
.demo-header {
display: flex;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.75rem;
}
.demo-header .icon { font-size: 1.25rem; }
.demo-header .title { font-weight: bold; font-size: 1rem; }
.demo-header .subtitle { color: var(--vp-c-text-2); font-size: 0.85rem; margin-left: 0.5rem; }
.type-quadrant {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.quadrant-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.quadrant-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
}
.quadrant-cell {
padding: 0.5rem;
border-radius: 6px;
text-align: center;
}
.strong-static { background: #d4edda; }
.weak-static { background: #fff3cd; }
.strong-dynamic { background: #cce5ff; }
.weak-dynamic { background: #f8d7da; }
.cell-label {
font-weight: bold;
font-size: 0.8rem;
margin-bottom: 0.25rem;
}
.cell-langs {
font-size: 0.75rem;
color: var(--vp-c-text-2);
margin-bottom: 0.15rem;
}
.cell-desc {
font-size: 0.7rem;
color: var(--vp-c-text-3);
}
.axis-labels {
display: flex;
justify-content: space-between;
margin-top: 0.5rem;
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.type-demo {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.demo-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.code-comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.5rem;
}
.code-block {
background: var(--vp-c-bg-alt);
border-radius: 4px;
overflow: hidden;
}
.code-label {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
background: var(--vp-c-divider);
}
pre {
margin: 0;
padding: 0.5rem;
font-size: 0.75rem;
overflow-x: auto;
}
code {
font-family: monospace;
}
.code-result {
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
text-align: center;
}
.code-result.error {
background: #f8d7da;
color: #721c24;
}
.code-result.success {
background: #d4edda;
color: #155724;
}
.conversion-demo {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.conversion-tabs {
display: flex;
gap: 0.5rem;
margin-bottom: 0.5rem;
flex-wrap: wrap;
}
.tab-btn {
padding: 0.35rem 0.6rem;
border: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-alt);
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
}
.tab-btn.active {
background: var(--vp-c-brand);
color: white;
border-color: var(--vp-c-brand);
}
.conversion-content {
display: flex;
flex-direction: column;
gap: 0.35rem;
}
.conversion-item {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.35rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
font-size: 0.8rem;
}
.code-expr {
background: var(--vp-c-divider);
padding: 0.15rem 0.4rem;
border-radius: 3px;
font-family: monospace;
}
.arrow {
color: var(--vp-c-text-2);
}
.code-result {
background: var(--vp-c-brand-soft);
padding: 0.15rem 0.4rem;
border-radius: 3px;
font-family: monospace;
}
.code-result.error {
background: #f8d7da;
color: #721c24;
}
.explanation {
color: var(--vp-c-text-2);
font-size: 0.75rem;
}
.type-inference {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
margin-bottom: 1rem;
}
.inference-examples {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 0.5rem;
}
.inference-item {
padding: 0.4rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
}
.inference-lang {
font-size: 0.7rem;
color: var(--vp-c-brand);
font-weight: bold;
}
.inference-code {
display: block;
font-family: monospace;
font-size: 0.8rem;
margin: 0.25rem 0;
}
.inference-result {
font-size: 0.75rem;
color: var(--vp-c-text-2);
}
.inference-result .type {
color: var(--vp-c-brand);
font-weight: bold;
}
.type-benefits {
background: var(--vp-c-bg);
padding: 0.75rem;
border-radius: 6px;
}
.benefits-title {
font-weight: bold;
font-size: 0.9rem;
margin-bottom: 0.5rem;
}
.benefits-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 0.5rem;
}
.benefit-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 0.4rem;
background: var(--vp-c-bg-alt);
border-radius: 4px;
text-align: center;
}
.benefit-icon { font-size: 1rem; }
.benefit-name { font-size: 0.8rem; font-weight: bold; }
.benefit-desc { font-size: 0.7rem; color: var(--vp-c-text-2); }
.info-box {
background: var(--vp-c-bg-alt);
padding: 0.75rem;
border-radius: 6px;
font-size: 0.85rem;
color: var(--vp-c-text-2);
margin-top: 0.75rem;
display: flex;
gap: 0.25rem;
}
.info-box .icon { flex-shrink: 0; }
@media (max-width: 640px) {
.code-comparison {
grid-template-columns: 1fr;
}
}
</style>
+41
View File
@@ -107,6 +107,26 @@ import TcpUdpComparison from './components/appendix/web-basics/TcpUdpComparison.
import SubnetCalculator from './components/appendix/web-basics/SubnetCalculator.vue'
import NetworkTroubleshooting from './components/appendix/web-basics/NetworkTroubleshooting.vue'
// Computer Fundamentals Components
import TransistorDemo from './components/appendix/computer-fundamentals/TransistorDemo.vue'
import LogicGateDemo from './components/appendix/computer-fundamentals/LogicGateDemo.vue'
import AdderDemo from './components/appendix/computer-fundamentals/AdderDemo.vue'
import CpuArchitectureDemo from './components/appendix/computer-fundamentals/CpuArchitectureDemo.vue'
import ProcessDemo from './components/appendix/computer-fundamentals/ProcessDemo.vue'
import MemoryDemo from './components/appendix/computer-fundamentals/MemoryDemo.vue'
import FilesystemDemo from './components/appendix/computer-fundamentals/FilesystemDemo.vue'
import EncodingDemo from './components/appendix/computer-fundamentals/EncodingDemo.vue'
import StorageDemo from './components/appendix/computer-fundamentals/StorageDemo.vue'
import TransmissionDemo from './components/appendix/computer-fundamentals/TransmissionDemo.vue'
import DataStructureDemo from './components/appendix/computer-fundamentals/DataStructureDemo.vue'
import AlgorithmDemo from './components/appendix/computer-fundamentals/AlgorithmDemo.vue'
import LanguageMapDemo from './components/appendix/computer-fundamentals/LanguageMapDemo.vue'
import TypeSystemDemo from './components/appendix/computer-fundamentals/TypeSystemDemo.vue'
import CompilerDemo from './components/appendix/computer-fundamentals/CompilerDemo.vue'
import CFNetworkLayers from './components/appendix/computer-fundamentals/NetworkLayers.vue'
import CFSubnetCalculator from './components/appendix/computer-fundamentals/SubnetCalculator.vue'
import CFTcpUdpComparison from './components/appendix/computer-fundamentals/TcpUdpComparison.vue'
// Deployment appendix components
import DeploymentOverviewDemo from './components/appendix/deployment/DeploymentOverviewDemo.vue'
import DeploymentBuildDemo from './components/appendix/deployment/DeploymentBuildDemo.vue'
@@ -611,6 +631,27 @@ export default {
app.component('TcpUdpComparison', TcpUdpComparison)
app.component('SubnetCalculator', SubnetCalculator)
app.component('NetworkTroubleshooting', NetworkTroubleshooting)
// Computer Fundamentals Components Registration
app.component('TransistorDemo', TransistorDemo)
app.component('LogicGateDemo', LogicGateDemo)
app.component('AdderDemo', AdderDemo)
app.component('CpuArchitectureDemo', CpuArchitectureDemo)
app.component('ProcessDemo', ProcessDemo)
app.component('MemoryDemo', MemoryDemo)
app.component('FilesystemDemo', FilesystemDemo)
app.component('EncodingDemo', EncodingDemo)
app.component('StorageDemo', StorageDemo)
app.component('TransmissionDemo', TransmissionDemo)
app.component('DataStructureDemo', DataStructureDemo)
app.component('AlgorithmDemo', AlgorithmDemo)
app.component('LanguageMapDemo', LanguageMapDemo)
app.component('TypeSystemDemo', TypeSystemDemo)
app.component('CompilerDemo', CompilerDemo)
app.component('CFNetworkLayers', CFNetworkLayers)
app.component('CFSubnetCalculator', CFSubnetCalculator)
app.component('CFTcpUdpComparison', CFTcpUdpComparison)
// Deployment appendix
app.component('DeploymentOverviewDemo', DeploymentOverviewDemo)
app.component('DeploymentBuildDemo', DeploymentBuildDemo)
@@ -1,3 +1,230 @@
# 算法思维入门
> 待实现
::: tip 🎯 核心问题
**如何高效地解决问题?** 你可能遇到过这样的困惑:同一个问题,有人写的代码跑几秒就出结果,有人写的跑几分钟还在转。差别往往在于算法。本章带你理解算法的核心思维方式。
:::
---
## 0. 全景图:算法是什么?
想象你要在一本字典里找一个单词:
- **方法一**:从第一页开始,一页一页翻(线性查找)
- **方法二**:根据首字母定位,再二分查找(二分查找)
两种方法都能找到,但效率天差地别。**算法就是解决问题的方法**。
<AlgorithmDemo />
**算法的核心指标:**
| 指标 | 含义 | 为什么重要 |
|------|------|-----------|
| **时间复杂度** | 运行时间随数据量增长的趋势 | 预测大规模数据的性能 |
| **空间复杂度** | 内存占用随数据量增长的趋势 | 评估内存消耗 |
| **正确性** | 是否总能得到正确结果 | 算法的基本要求 |
::: tip 📊 逐行解读这张表
**时间复杂度**:用大 O 表示法描述。O(n) 表示数据量翻倍,时间翻倍;O(n²) 表示数据量翻倍,时间变成 4 倍。
**空间复杂度**:同样用大 O 表示法。有些算法用空间换时间(如哈希表),有些用时间换空间(如压缩算法)。
**正确性**:算法必须对所有可能的输入都能给出正确结果。边界条件(空输入、极大输入)最容易出错。
:::
---
## 1. 二分查找:每次排除一半
### 1.1 二分查找的原理
::: tip 💡 二分查找如何工作?
**前提**:数据必须有序
**过程**
1. 找到中间元素
2. 如果中间元素等于目标,找到!
3. 如果目标小于中间元素,在左半部分继续
4. 如果目标大于中间元素,在右半部分继续
5. 每次排除一半,直到找到或确定不存在
**时间复杂度**O(log n)
**生活类比**:猜数字游戏。我想一个 1-100 的数,你每次猜中间,我告诉你大了还是小了。最多猜 7 次就能猜中(因为 2⁷ = 128 > 100)。
:::
### 1.2 为什么二分查找这么快?
| 数据量 | 线性查找 | 二分查找 |
|--------|---------|---------|
| 100 | 100 次 | 7 次 |
| 1,000 | 1,000 次 | 10 次 |
| 1,000,000 | 1,000,000 次 | 20 次 |
| 1,000,000,000 | 1,000,000,000 次 | 30 次 |
::: tip 💡 对数增长的威力
二分查找的时间复杂度是 O(log n),这意味着:
- 10 亿数据,最多查找 30 次
- 1 万亿数据,最多查找 40 次
这就是对数增长的威力——数据量增加 1000 倍,查找次数只增加 10 次。
:::
---
## 2. 排序:将无序变有序
### 2.1 常见排序算法
| 算法 | 时间复杂度 | 特点 | 适用场景 |
|------|-----------|------|---------|
| **冒泡排序** | O(n²) | 简单但慢 | 教学、小数据量 |
| **选择排序** | O(n²) | 简单但慢 | 小数据量 |
| **插入排序** | O(n²) | 对近乎有序的数据快 | 小数据、近乎有序 |
| **快速排序** | O(n log n) | 实际最快 | 通用排序 |
| **归并排序** | O(n log n) | 稳定排序 | 需要稳定性的场景 |
| **堆排序** | O(n log n) | 原地排序 | 内存受限场景 |
### 2.2 为什么快速排序"快"
::: tip 💡 快速排序的原理
**核心思想**:分治法
1. 选一个"基准"元素
2. 把比基准小的放左边,比基准大的放右边
3. 对左右两部分递归排序
4. 合并结果
**为什么快?**
- 每次划分后,基准元素就到了最终位置
- 平均情况下,每次划分大约排除一半元素
- 时间复杂度 O(n log n)
**生活类比**:整理书架。先抽出一本书,把比它薄的放左边,比它厚的放右边。然后对左右两堆分别重复这个过程。
:::
---
## 3. 递归:自己调用自己
### 3.1 递归的本质
::: tip 💡 什么是递归?
**递归**是函数调用自身的编程技巧。
**两个关键要素**
1. **基本情况**:什么时候停止递归?
2. **递归步骤**:如何把问题分解成更小的子问题?
**经典例子:阶乘**
```js
function factorial(n) {
if (n <= 1) return 1 // 基本情况
return n * factorial(n - 1) // 递归步骤
}
```
**生活类比**:俄罗斯套娃。打开一个娃娃,里面是更小的娃娃,直到最小的那个打不开为止。
:::
### 3.2 递归 vs 迭代
| 特性 | 递归 | 迭代(循环) |
|------|------|-------------|
| **代码简洁度** | 通常更简洁 | 可能更复杂 |
| **内存消耗** | 较高(调用栈) | 较低 |
| **性能** | 稍慢(函数调用开销) | 更快 |
| **适用场景** | 树遍历、分治算法 | 简单重复任务 |
::: warning ⚠️ 递归的陷阱
**栈溢出**:递归层次太深,调用栈空间耗尽。
**解决方法**
- 改用迭代
- 使用尾递归优化(某些语言支持)
- 限制递归深度
:::
---
## 4. 贪心算法:每步选最优
### 4.1 贪心的思想
::: tip 💡 什么是贪心算法?
**贪心算法**在每一步都选择当前看起来最优的选择,希望最终得到全局最优解。
**适用条件**
1. **贪心选择性质**:局部最优能导致全局最优
2. **最优子结构**:问题的最优解包含子问题的最优解
**经典例子:硬币找零**
- 目标:用最少的硬币凑出指定金额
- 贪心策略:每次选最大的硬币
- 结果:67 元 = 50 + 10 + 5 + 1 + 15 枚)
**生活类比**:登山时,每次都选最陡的路往上走。虽然不一定能到最高峰,但通常能到不错的位置。
:::
### 4.2 贪心的局限性
::: warning ⚠️ 贪心不一定得到最优解
**反例:硬币找零**
如果硬币面值是 [1, 3, 4],要凑 6 元:
- 贪心:4 + 1 + 1 = 3 枚
- 最优:3 + 3 = 2 枚
贪心算法在这里失败了!
**教训**:贪心算法简单高效,但不总是能得到最优解。使用前要证明问题满足贪心条件。
:::
---
## 5. 算法设计范式
| 范式 | 思想 | 典型算法 | 适用问题 |
|------|------|---------|---------|
| **分治** | 把问题分解成小问题 | 快速排序、归并排序 | 可分解的问题 |
| **贪心** | 每步选最优 | 最小生成树、霍夫曼编码 | 有贪心性质的问题 |
| **动态规划** | 记录子问题的解 | 背包问题、最短路径 | 有重叠子问题 |
| **回溯** | 试错,走不通就回退 | 八皇后、全排列 | 搜索问题 |
---
## 6. 总结:算法是解决问题的艺术
让我们用一个比喻总结各种算法思想:
| 思想 | 比喻 | 核心要点 |
|------|------|---------|
| **二分查找** | 猜数字 | 每次排除一半 |
| **排序** | 整理书架 | 建立秩序 |
| **递归** | 俄罗斯套娃 | 化大为小 |
| **贪心** | 登山选路 | 局部最优 |
::: tip 💡 核心启示
**算法的本质是"效率"和"正确性"的平衡。**
- 好的算法能让程序效率提升几个数量级
- 但过度优化可能引入复杂性
- 先保证正确,再追求效率
理解算法思维,比记住具体算法更重要:
- 分治:把大问题分解成小问题
- 贪心:每步选最优
- 动态规划:记录子问题的解
- 回溯:试错,走不通就回退
:::
---
## 延伸阅读
- **算法导论**:系统学习算法的经典教材
- **LeetCode**:通过刷题提升算法能力
- **算法可视化**:直观理解算法执行过程
- **竞赛算法**:学习更高级的算法技巧
@@ -9,7 +9,7 @@
现代计算机网络就像一个**快递公司**,采用五层分层模型,每层负责不同的工作:
<NetworkLayers />
<CFNetworkLayers />
::: tip 💡 为什么需要分层?
想象一个没有分工的快递公司:
@@ -309,7 +309,7 @@ IP: 192.168.1.10
- `/24` 表示前 24 位是网络位
- 剩余 8 位是主机位(2^8 - 2 = 254 个可用 IP)
<SubnetCalculator />
<CFSubnetCalculator />
### 3.3 路由器:GPS 导航
@@ -431,7 +431,7 @@ PING google.com (142.250.185.238): 56 data bytes
### 4.2 TCP vs UDP:挂号信 vs 平信
<TcpUdpComparison />
<CFTcpUdpComparison />
**选择建议**:
@@ -1,3 +1,244 @@
# 数据的编码、存储与传输
> 待实现
::: tip 🎯 核心问题
**计算机如何表示和存储各种数据?** 文字、图片、视频、声音...这些在现实世界中形态各异的信息,是如何变成 0 和 1 的?又是如何存储和传输的?本章带你理解数据的编码、存储和传输原理。
:::
---
## 0. 全景图:数据的生命周期
想象你要寄一封信给朋友:
1. **编码**:把想法变成文字(信息编码)
2. **存储**:写在纸上(数据存储)
3. **传输**:通过邮局寄出(数据传输)
计算机处理数据也是类似的过程:
| 阶段 | 做什么 | 核心问题 | 类比 |
|------|--------|---------|------|
| **编码** | 把信息变成 0 和 1 | 如何用二进制表示各种数据? | 把想法变成文字 |
| **存储** | 把数据保存起来 | 数据存在哪里?怎么组织? | 写在纸上 |
| **传输** | 把数据送到别处 | 如何可靠、高效地传输? | 邮局寄信 |
::: tip 📊 逐行解读这张表
**编码**:计算机只认识 0 和 1,所以所有数据都要"翻译"成二进制。文字用 ASCII 或 Unicode 编码,数字用二进制表示,图片用像素值,声音用采样值。
**存储**:编码后的数据需要保存起来。存储介质从快到慢有:寄存器 → 缓存 → 内存 → SSD → 硬盘 → 云存储。越快的存储越贵、容量越小。
**传输**:数据需要在不同设备间流动。传输方式有串行(一位一位传)和并行(多位同时传)。现代高速接口(USB、PCIe)多采用串行方式。
:::
---
## 1. 数据编码:用 0 和 1 表示一切
### 1.1 文本编码
<EncodingDemo />
::: tip 💡 字符编码的演变
**ASCII1963年)**
- 用 7 位二进制表示 128 个字符
- 包括英文字母、数字、常用符号
- 问题:只能表示英语,无法表示中文等
**Unicode1991年)**
- 统一编码标准,覆盖世界上所有文字
- 目前已收录超过 14 万个字符
- 常用编码方式:UTF-8(变长编码,1-4 字节)
**UTF-8 的巧妙设计**
- ASCII 字符(0-127)只用 1 字节,完全兼容
- 常用汉字用 3 字节
- 根据"前导位"判断一个字符占几个字节
:::
**常见字符编码对比:**
| 编码 | 字节数 | 支持字符 | 特点 |
|------|--------|---------|------|
| **ASCII** | 1 字节 | 128 个 | 仅英语,兼容性好 |
| **UTF-8** | 1-4 字节 | 所有文字 | 变长编码,主流标准 |
| **UTF-16** | 2-4 字节 | 所有文字 | 定长为主,Windows 常用 |
| **GBK** | 1-2 字节 | 中英文 | 中文专用,不推荐新项目使用 |
### 1.2 数字编码
::: tip 💡 整数如何用二进制表示?
**无符号整数**:直接用二进制表示
- 8 位可以表示 0-255
- 32 位可以表示 0 到约 42 亿
**有符号整数**:用补码表示
- 最高位是符号位(0 正 1 负)
- 正数:直接用二进制
- 负数:正数的二进制取反加 1
**为什么用补码?**
- 加法减法统一处理
- 0 的表示唯一
- 硬件实现简单
:::
**浮点数表示(IEEE 754 标准):**
| 部分 | 作用 | 位数(32位浮点) |
|------|------|-----------------|
| **符号位** | 正负 | 1 位 |
| **指数位** | 决定大小范围 | 8 位 |
| **尾数位** | 决定精度 | 23 位 |
### 1.3 多媒体编码
**图像编码**
- **位图**:每个像素用 RGB 值表示(红绿蓝各 8 位)
- **压缩**:JPEG(有损)、PNG(无损)
- **矢量图**:用数学公式描述形状(SVG)
**音频编码**
- **采样**:把连续声波变成离散点
- **量化**:把采样值变成数字
- **压缩**:MP3(有损)、FLAC(无损)
**视频编码**
- 视频是一帧帧图像
- 关键技术:帧间压缩(只记录变化部分)
- 常见格式:H.264、H.265、VP9
---
## 2. 数据存储:速度与容量的权衡
### 2.1 存储层次结构
<StorageDemo />
### 2.2 存储器类型
| 类型 | 原理 | 特点 | 应用 |
|------|------|------|------|
| **SRAM** | 触发器 | 极快,但昂贵 | CPU 缓存 |
| **DRAM** | 电容充放电 | 较快,需刷新 | 内存 |
| **Flash** | 浮栅晶体管 | 断电不丢失,有写入寿命 | SSD、U 盘 |
| **HDD** | 磁盘磁性记录 | 容量大,有机械延迟 | 机械硬盘 |
### 2.3 存储的关键指标
::: tip 💡 如何评估存储性能?
**访问时间**:从发出请求到获得数据的时间
- 内存:约 100 纳秒
- SSD:约 100 微秒
- HDD:约 10 毫秒
**吞吐量**:单位时间能传输的数据量
- 内存:几十 GB/s
- SSD:几 GB/s
- HDD100-200 MB/s
**IOPS**:每秒能进行的读写操作次数
- SSD:几万到几十万
- HDD:几百
:::
---
## 3. 数据传输:从串行到并行
### 3.1 传输方式
<TransmissionDemo />
### 3.2 常见接口标准
| 接口 | 类型 | 速度 | 应用 |
|------|------|------|------|
| **USB 3.0** | 串行 | 5 Gbps | 外设连接 |
| **USB 4** | 串行 | 40 Gbps | 高速外设 |
| **SATA III** | 串行 | 6 Gbps | 硬盘接口 |
| **PCIe 4.0 x16** | 串行(多通道) | 32 GB/s | 显卡、SSD |
| **以太网** | 串行 | 1-100 Gbps | 网络传输 |
### 3.3 传输的可靠性
::: tip 💡 如何保证传输不出错?
**校验机制**
- **奇偶校验**:简单的错误检测
- **CRC 校验**:更强的错误检测能力
- **校验和**:快速检测数据完整性
**纠错机制**
- **重传**:发现错误就重新发送
- **前向纠错**:发送冗余信息,接收方能自动纠正
**流量控制**
- 防止发送方发太快,接收方来不及处理
- 类似"确认收到再发下一个"
:::
---
## 4. 编码、存储、传输的协作
让我们看一个完整的例子:**保存一张照片到云端**
```
1. 编码阶段
- 相机传感器捕捉光线 → 模拟信号
- ADC 转换 → 数字信号(RAW 格式)
- JPEG 编码 → 压缩后的二进制数据
2. 存储阶段
- 写入手机内存(RAM)→ 临时存储
- 写入手机闪存(Flash)→ 持久存储
3. 传输阶段
- 读取闪存数据 → 内存
- 通过 Wi-Fi/4G 发送 → 网络传输
- 云端接收 → 写入云端存储
```
::: tip 💡 理解这个流程
每一步都涉及编码、存储、传输:
1. **编码**:把图像变成二进制数据
2. **存储**:在本地保存
3. **传输**:通过网络发送到云端
这三个环节紧密配合,才能完成"保存照片到云端"这个看似简单的操作。
:::
---
## 5. 总结:数据的三重奏
让我们用一个比喻总结编码、存储、传输:
| 概念 | 比喻 | 核心任务 |
|------|------|---------|
| **编码** | 翻译 | 把信息变成 0 和 1 |
| **存储** | 仓库 | 把数据保存起来 |
| **传输** | 快递 | 把数据送到目的地 |
::: tip 💡 核心启示
**数据处理的本质是"转换、保存、移动"**
- 编码解决"如何表示"的问题
- 存储解决"如何保存"的问题
- 传输解决"如何传递"的问题
理解了这三点,你就会明白:
- 为什么不同文件格式要选择不同的编码方式
- 为什么需要不同层次的存储介质
- 为什么传输速度和可靠性需要平衡
:::
---
## 延伸阅读
- **字符编码详解**:深入学习 ASCII、Unicode、UTF-8 的设计原理
- **存储技术发展**:了解从磁带到 SSD 的技术演进
- **网络传输协议**:学习 TCP/IP 如何保证可靠传输
- **数据压缩算法**:了解 ZIP、JPEG、MP3 等压缩原理
@@ -1,3 +1,214 @@
# 数据结构
> 待实现
::: tip 🎯 核心问题
**如何高效地组织和存储数据?** 你可能遇到过这样的困惑:为什么有些程序处理几万条数据很快,有些处理几百条就卡住了?答案往往在于数据结构的选择。本章带你理解常见数据结构的特点和适用场景。
:::
---
## 0. 全景图:数据结构是什么?
想象你要整理一堆书:
- **堆在地上**:找书要一本本翻(链表)
- **按编号放书架**:直接去对应位置拿(数组)
- **按类别分柜子**:先找柜子再找书(哈希表)
- **按书名排序**:二分查找,每次排除一半(树)
不同的整理方式,找书的效率天差地别。**数据结构就是数据的"整理方式"**。
<DataStructureDemo />
**常见数据结构分类:**
| 类型 | 特点 | 典型代表 | 适用场景 |
|------|------|---------|---------|
| **线性结构** | 数据排成一排 | 数组、链表、栈、队列 | 顺序处理、历史记录 |
| **哈希结构** | 键值对映射 | 哈希表 | 快速查找、缓存 |
| **树形结构** | 层次关系 | 二叉树、B树 | 排序、搜索、文件系统 |
| **图结构** | 网状关系 | 有向图、无向图 | 社交网络、路径规划 |
::: tip 📊 逐行解读这张表
**线性结构**:最简单的数据组织方式,数据一个接一个排列。数组适合随机访问,链表适合频繁插入删除。
**哈希结构**:用"键"直接找到"值",查找速度最快。但需要处理"冲突"问题(两个键映射到同一位置)。
**树形结构**:有层次关系的数据。二叉搜索树适合排序和搜索,B树适合磁盘存储(数据库索引)。
**图结构**:最复杂的结构,表示任意的关系网络。社交网络、地图导航都用图来建模。
:::
---
## 1. 线性结构:最基础的组织方式
### 1.1 数组:连续存储
::: tip 💡 数组的特点
**数组**是一块连续的内存空间,每个元素大小相同。
**优点**
- 随机访问快:`arr[100]` 直接计算地址,O(1)
- 缓存友好:连续存储,CPU 缓存命中率高
**缺点**
- 插入删除慢:需要移动后面所有元素,O(n)
- 大小固定:需要预先分配空间
**生活类比**:一排编号的储物柜,每个柜子大小相同。找第 10 号柜子直接去,但要在中间插入一个柜子,后面的都要往后挪。
:::
### 1.2 链表:节点相连
::: tip 💡 链表的特点
**链表**由一系列节点组成,每个节点包含数据和指向下一个节点的指针。
**优点**
- 插入删除快:只需修改指针,O(1)
- 大小灵活:可以动态增长
**缺点**
- 访问慢:要从头开始遍历,O(n)
- 额外空间:每个节点需要存储指针
**生活类比**:寻宝游戏,每个线索指向下一个地点。要找第 10 个线索,必须从第 1 个开始一步步找。
:::
### 1.3 栈和队列:受限的线性结构
| 结构 | 规则 | 操作 | 类比 | 应用 |
|------|------|------|------|------|
| **栈** | 后进先出 (LIFO) | push/pop | 一摞盘子 | 函数调用、撤销操作 |
| **队列** | 先进先出 (FIFO) | enqueue/dequeue | 排队买票 | 任务调度、消息队列 |
::: tip 💡 为什么要有"受限"的结构?
栈和队列看起来比数组、链表功能少,但正是这种"限制"让它们有明确的用途:
- **栈**:函数调用时,最后调用的函数最先返回
- **队列**:任务调度时,先来的任务先处理
限制带来简洁,简洁带来高效。
:::
---
## 2. 哈希表:最快的查找
### 2.1 哈希表原理
::: tip 💡 哈希表如何工作?
**哈希表**通过"哈希函数"把键映射到数组索引。
**工作流程**
1. 输入键(如 "apple"
2. 哈希函数计算:`hash("apple") = 3`
3. 直接去数组索引 3 的位置找
**冲突处理**
- 两个不同的键可能映射到同一索引
- 解决方法:链地址法(同一位置用链表存储多个值)
**生活类比**:图书馆按书名首字母分柜子。"Apple" 开头的书都放 A 柜,"Banana" 开头的放 B 柜。找书时先确定柜子,再在柜子里找。
:::
### 2.2 哈希表的时间复杂度
| 操作 | 平均情况 | 最坏情况 |
|------|---------|---------|
| **查找** | O(1) | O(n) |
| **插入** | O(1) | O(n) |
| **删除** | O(1) | O(n) |
::: warning ⚠️ 什么时候会退化?
当所有键都映射到同一个索引时,哈希表退化为链表,所有操作变成 O(n)。
**避免方法**
- 选择好的哈希函数
- 动态扩容(负载因子超过阈值时扩容)
:::
---
## 3. 树:层次结构
### 3.1 二叉搜索树
::: tip 💡 二叉搜索树的规则
**二叉搜索树**是一种特殊的二叉树:
- 左子树的所有值 < 根节点
- 右子树的所有值 > 根节点
**查找过程**
1. 从根节点开始
2. 如果目标值 < 当前值,往左走
3. 如果目标值 > 当前值,往右走
4. 每次比较排除一半节点
**时间复杂度**:O(log n),但最坏情况(变成链表)是 O(n)
:::
### 3.2 平衡树
为了防止二叉搜索树退化,引入了**平衡树**:
| 类型 | 平衡方式 | 特点 |
|------|---------|------|
| **AVL 树** | 严格平衡(高度差 ≤ 1) | 查找最快,插入删除稍慢 |
| **红黑树** | 近似平衡 | 综合性能好,应用最广 |
| **B 树** | 多路平衡 | 适合磁盘存储,数据库索引 |
---
## 4. 如何选择数据结构?
| 需求 | 推荐结构 | 原因 |
|------|---------|------|
| **快速随机访问** | 数组 | O(1) 索引访问 |
| **频繁插入删除** | 链表 | O(1) 插入删除 |
| **快速查找** | 哈希表 | O(1) 平均查找 |
| **有序数据** | 平衡树 | O(log n) 查找,保持有序 |
| **最近使用** | 栈 | LIFO 特性 |
| **任务排队** | 队列 | FIFO 特性 |
::: tip 💡 选择数据结构的心法
**没有最好的数据结构,只有最合适的数据结构。**
选择时要考虑:
1. **主要操作是什么?** 查找?插入?删除?
2. **数据量多大?** 小数据量差别不大,大数据量要慎重
3. **数据有序吗?** 有序数据可以用二分查找
4. **内存限制?** 某些结构需要额外空间
:::
---
## 5. 总结:数据结构是程序的基础
让我们用一个比喻总结各种数据结构:
| 结构 | 比喻 | 核心特点 |
|------|------|---------|
| **数组** | 编号储物柜 | 访问快,插入慢 |
| **链表** | 寻宝线索 | 插入快,访问慢 |
| **栈** | 一摞盘子 | 后进先出 |
| **队列** | 排队队伍 | 先进先出 |
| **哈希表** | 分类柜子 | 查找最快 |
| **树** | 家族族谱 | 层次结构 |
::: tip 💡 核心启示
**数据结构决定了程序的效率上限。**
- 选对数据结构,问题迎刃而解
- 选错数据结构,再好的算法也无济于事
理解数据结构,就是理解"如何高效地组织数据"。这是每个程序员的基本功。
:::
---
## 延伸阅读
- **数据结构实现**:自己动手实现各种数据结构,加深理解
- **高级数据结构**:学习跳表、布隆过滤器、并查集等
- **数据库索引**:了解 B+ 树在数据库中的应用
- **缓存设计**:学习 LRU 缓存如何结合哈希表和链表
@@ -1,3 +1,255 @@
# 操作系统(进程 / 内存 / 文件系统)
> 待实现
::: tip 🎯 核心问题
**操作系统是做什么的?** 你可能每天都在用 Windows、macOS 或 Linux,但你知道它到底在忙什么吗?为什么需要它?没有它电脑还能用吗?本章带你理解操作系统的三大核心职责:管理进程、管理内存、管理文件。
:::
---
## 0. 全景图:操作系统的角色
想象你开了一家餐厅。你需要:
- **安排员工工作**:谁做菜、谁端盘子、谁收银(进程管理)
- **管理厨房空间**:冰箱放什么、操作台怎么分配(内存管理)
- **整理仓库物资**:食材怎么存放、怎么找(文件系统)
操作系统就是电脑的"餐厅经理",它负责协调所有资源,让程序能顺利运行。
**操作系统的三大核心职责:**
| 职责 | 管理对象 | 核心问题 | 类比 |
|------|---------|---------|------|
| **进程管理** | CPU 时间 | 谁先用 CPU?用多久? | 员工排班 |
| **内存管理** | 内存空间 | 程序放哪里?怎么不冲突? | 厨房空间分配 |
| **文件系统** | 磁盘数据 | 数据怎么存?怎么找? | 仓库物资管理 |
::: tip 📊 逐行解读这张表
**进程管理**:CPU 是最宝贵的资源,操作系统要决定哪个程序先用、用多久。就像餐厅经理安排员工轮班,不能让所有人同时挤在厨房里。
**内存管理**:内存是程序的"工作台",操作系统要给每个程序分配空间,还要保证它们互不干扰。就像厨房空间有限,要合理分配给不同的厨师。
**文件系统**:磁盘是"仓库",操作系统要把数据有序地存进去,需要时能快速找到。就像仓库管理员整理货架,按类别、编号存放。
:::
---
## 1. 进程管理:程序的"分身术"
### 1.1 什么是进程?
<ProcessDemo />
::: tip 💡 程序 vs 进程
这是初学者最容易混淆的概念:
| 概念 | 定义 | 类比 | 特点 |
|------|------|------|------|
| **程序** | 静态的代码文件 | 菜谱 | 存在磁盘上,不会动 |
| **进程** | 程序的运行实例 | 正在按菜谱做菜 | 在内存中运行,会变化 |
**关键区别**
- 一个程序可以启动多个进程(比如打开多个浏览器窗口)
- 每个进程有独立的内存空间,互不干扰
- 进程有生命周期:创建、运行、等待、终止
:::
### 1.2 进程的状态
进程在运行过程中会在不同状态之间切换:
| 状态 | 含义 | 什么时候进入 | 类比 |
|------|------|-------------|------|
| **就绪 (Ready)** | 准备好运行,等 CPU | 进程刚创建,或从等待恢复 | 员工在休息室等排班 |
| **运行 (Running)** | 正在 CPU 上执行 | 被调度器选中 | 员工正在工作 |
| **等待 (Waiting)** | 等待 I/O 或其他资源 | 需要读磁盘、等网络 | 员工在等食材送达 |
| **终止 (Terminated)** | 运行结束 | 程序退出或出错 | 员工下班 |
### 1.3 进程调度:谁先用 CPU
::: tip 💡 为什么需要调度?
CPU 核心数有限,但进程可能有几十上百个。操作系统需要决定:
- 哪个进程先运行?
- 运行多久?
- 什么时候切换?
这就是**进程调度**要解决的问题。
:::
**常见调度算法:**
| 算法 | 思路 | 优点 | 缺点 |
|------|------|------|------|
| **先来先服务 (FCFS)** | 谁先到谁先运行 | 简单公平 | 短任务可能等很久 |
| **短作业优先 (SJF)** | 短任务优先 | 平均等待时间最短 | 需要预知任务长度 |
| **时间片轮转 (RR)** | 每人运行一小段时间 | 公平,响应快 | 切换开销大 |
| **优先级调度** | 重要任务优先 | 重要任务响应快 | 可能导致低优先级任务饿死 |
---
## 2. 内存管理:程序的"工作台"
### 2.1 为什么需要内存管理?
<MemoryDemo />
::: tip 💡 如果没有内存管理会怎样?
想象一个没有管理的厨房:
- **冲突**:两个厨师同时用同一个灶台,菜都糊了
- **浪费**:有人占了整个厨房,其他人没地方做饭
- **安全问题**:有人偷吃了别人的食材
操作系统通过**内存管理**解决这些问题:
- 给每个进程分配独立的内存空间
- 防止进程互相干扰(内存保护)
- 高效利用有限的内存资源
:::
### 2.2 虚拟内存:让每个进程都"以为"自己独占内存
::: tip 💡 什么是虚拟内存?
**虚拟内存**是操作系统的一个"魔术":
- 每个进程都以为自己有 4GB(或更多)的内存空间
- 实际上物理内存可能只有 8GB、16GB
- 操作系统通过"映射"把虚拟地址转换成物理地址
**生活类比**:想象一个酒店:
- 每个客人都以为自己独占整个酒店(虚拟空间)
- 实际上酒店只有 100 间房(物理内存)
- 前台(操作系统)负责分配房间、记录谁住哪里
:::
**虚拟内存的好处:**
| 好处 | 说明 | 为什么重要 |
|------|------|-----------|
| **隔离保护** | 进程间内存互不干扰 | 一个崩溃不影响其他 |
| **内存扩展** | 用磁盘当内存用 | 可以运行比物理内存大的程序 |
| **简化编程** | 不用关心物理地址 | 程序员写代码更简单 |
### 2.3 内存分配策略
当进程需要内存时,操作系统如何分配?
| 策略 | 思路 | 特点 |
|------|------|------|
| **首次适应** | 找到第一个够大的空闲块 | 速度快 |
| **最佳适应** | 找最小的够大的空闲块 | 内存利用率高 |
| **最坏适应** | 找最大的空闲块 | 减少小碎片 |
---
## 3. 文件系统:数据的"档案柜"
### 3.1 什么是文件系统?
<FilesystemDemo />
::: tip 💡 文件系统是什么?
**文件系统**是操作系统管理磁盘数据的方式。
**生活类比**:想象一个图书馆:
- 书架 = 磁盘
- 书 = 文件
- 目录卡片 = inode
- 分类编号 = 路径
没有文件系统,磁盘就是一堆杂乱的数据。有了文件系统,我们可以:
- 用"路径"找到文件(如 `/home/user/document.txt`
- 创建、删除、修改文件
- 控制谁能访问哪些文件
:::
### 3.2 inode:文件的"身份证"
::: tip 💡 inode 是什么?
每个文件都有一个 **inode**(索引节点),记录了文件的元数据:
| 信息 | 说明 |
|------|------|
| inode 编号 | 文件的唯一标识 |
| 文件大小 | 多少字节 |
| 权限 | 谁能读写 |
| 时间戳 | 创建、修改、访问时间 |
| 数据块位置 | 文件内容存在哪些磁盘块 |
**关键理解**
- 文件名不在 inode 里!文件名只是目录中的一个条目
- 一个文件可以有多个名字(硬链接)
- 删除文件只是删除目录项,inode 可能还在
:::
### 3.3 常见文件系统
| 文件系统 | 操作系统 | 特点 |
|---------|---------|------|
| **NTFS** | Windows | 支持大文件、权限控制 |
| **APFS** | macOS | 加密、快照、高效 |
| **ext4** | Linux | 稳定、高效、广泛使用 |
| **FAT32** | 通用 | 兼容性好,但单文件最大 4GB |
| **exFAT** | 通用 | 支持大文件,适合 U 盘 |
---
## 4. 进程、内存、文件系统的协作
这三个子系统是如何配合工作的?让我们看一个完整的例子:
**场景:打开一个文档文件**
```
1. 用户双击文件
2. 文件系统:根据路径找到 inode,读取文件内容
3. 进程管理:创建新进程(文档编辑器),分配 PID
4. 内存管理:为新进程分配内存,加载程序代码和数据
5. 进程运行:编辑器进程读取文件内容,显示在屏幕上
```
::: tip 💡 理解这个流程
每一步都涉及操作系统的核心功能:
1. **文件系统**:负责"找到文件"
2. **进程管理**:负责"启动程序"
3. **内存管理**:负责"给程序分配空间"
这三者紧密协作,才能完成一个看似简单的"打开文件"操作。
:::
---
## 5. 总结:操作系统是"大管家"
让我们用一个比喻总结操作系统的三大职责:
| 职责 | 比喻 | 核心任务 |
|------|------|---------|
| **进程管理** | 餐厅排班员 | 安排谁先工作、工作多久 |
| **内存管理** | 厨房管理员 | 分配工作台、防止冲突 |
| **文件系统** | 仓库管理员 | 整理物资、快速查找 |
::: tip 💡 核心启示
**操作系统的本质是"资源管理"**
- CPU 时间是资源 → 进程管理
- 内存空间是资源 → 内存管理
- 磁盘空间是资源 → 文件系统
理解了这一点,你就会明白:
- 为什么电脑会变慢(进程太多、内存不足)
- 为什么需要重启(清理资源、释放内存)
- 为什么文件要整理(提高查找效率)
:::
---
## 延伸阅读
- **操作系统原理**:深入学习进程调度、内存分页、文件系统实现
- **Linux 系统编程**:学习如何与操作系统交互(系统调用)
- **并发编程**:学习多进程、多线程编程
- **系统监控**:学习使用 top、htop、vmstat 等工具监控系统状态
@@ -1,3 +1,398 @@
# 编程语言图谱
> 待实现
::: tip 🎯 核心问题
**为什么有这么多编程语言?它们之间有什么关系?** 从机器语言到现代高级语言,每种语言都有其设计哲学和适用场景。本章带你理解编程语言的演化历程和核心概念。
:::
---
## 0. 想象你要和外国人交流:
- **直接用肢体语言**:最原始,但效率极低(机器语言)
- **学习对方的语言**:需要翻译,但表达丰富(高级语言)
- **使用世界语**:设计完美,但没人用(某些学术语言)
- **使用翻译软件**:自动转换,但可能不准确(编译器/解释器)
**编程语言就是人类与计算机沟通的桥梁**,不同的语言有不同的设计哲学。
<LanguageMapDemo />
---
## 1. 编程语言的演化
### 1.1 第一代:机器语言(1940s)
::: tip 💡 机器语言是什么?
直接用 0 和 1 编写程序,计算机可以直接执行。
**示例**:让计算机计算 1 + 2
```
10110000 00000001 ; 将 1 放入寄存器
10110001 00000010 ; 将 2 放入另一个寄存器
10100010 ; 执行加法
```
**问题**
- 人类难以理解和记忆
- 容易出错,一个 0 写成 1 就全错了
- 不同 CPU 有不同的机器语言
:::
### 1.2 第二代:汇编语言(1950s)
用**助记符**代替 0 和 1
```asm
MOV AX, 1 ; 将 1 放入 AX 寄存器
MOV BX, 2 ; 将 2 放入 BX 寄存器
ADD AX, BX ; 将 BX 加到 AX
```
::: tip 💡 汇编语言 vs 机器语言
| 特性 | 机器语言 | 汇编语言 |
|------|---------|---------|
| **可读性** | 极差 | 较好 |
| **执行效率** | 最高 | 最高(汇编器直接转换) |
| **移植性** | 无 | 无(依赖 CPU 架构) |
| **使用场景** | 几乎不用 | 嵌入式、操作系统内核 |
:::
### 1.3 第三代:高级语言(1950s - 至今)
**用接近自然语言的方式编程**
```c
int sum = 1 + 2; // C 语言
```
**里程碑语言**
| 年代 | 语言 | 意义 |
|------|------|------|
| **1957** | Fortran | 第一个高级语言,科学计算 |
| **1958** | Lisp | 函数式编程鼻祖 |
| **1959** | COBOL | 商业数据处理 |
| **1972** | C | 系统编程,影响深远 |
| **1983** | C++ | 面向对象 + C 的效率 |
| **1991** | Python | 简洁优雅,AI 时代主角 |
| **1995** | Java | 跨平台,企业应用 |
| **1995** | JavaScript | Web 开发,无处不在 |
| **2009** | Go | 并发友好,云原生 |
| **2010** | Rust | 内存安全,系统编程新选择 |
### 1.4 第四代:领域特定语言(DSL)
为特定领域设计的语言:
| 语言 | 领域 | 示例 |
|------|------|------|
| **SQL** | 数据库查询 | `SELECT * FROM users` |
| **HTML** | 网页结构 | `<div>Hello</div>` |
| **CSS** | 样式定义 | `color: red;` |
| **Regex** | 文本匹配 | `\d{3}-\d{4}` |
| **MATLAB** | 数学计算 | `A = [1 2; 3 4]` |
---
## 2. 编程范式:思考问题的方式
::: tip 💡 什么是编程范式?
编程范式是**编程的思维方式**,决定了你如何组织代码和解决问题。
就像写作有不同的文体(诗歌、小说、论文),编程也有不同的"文体"。
:::
### 2.1 命令式编程(Imperative
**核心思想**:告诉计算机"怎么做"
```c
// 计算数组总和
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
```
**特点**
- 关注**过程**和**步骤**
- 通过**语句**改变程序状态
- 最接近计算机实际执行方式
**代表语言**C, Fortran, BASIC
### 2.2 面向对象编程(OOP
**核心思想**:把数据和操作封装在"对象"中
```python
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
print(f"{self.name} says woof!")
dog = Dog("Buddy")
dog.bark() # Buddy says woof!
```
**四大特性**
| 特性 | 含义 | 生活类比 |
|------|------|---------|
| **封装** | 隐藏内部细节 | 汽车方向盘,不需要知道引擎原理 |
| **继承** | 子类继承父类 | 儿子继承父亲的基因 |
| **多态** | 同一接口不同实现 | 不同动物发出不同叫声 |
| **抽象** | 提取共同特征 | "动物"是对猫、狗的抽象 |
**代表语言**Java, C++, Python, Ruby
### 2.3 函数式编程(Functional
**核心思想**:把计算视为函数求值,避免状态变化
```haskell
-- 计算数组总和
sum arr = foldl (+) 0 arr
-- 或者更简洁
sum = foldl (+) 0
```
**核心原则**
| 原则 | 含义 | 好处 |
|------|------|------|
| **纯函数** | 相同输入永远产生相同输出 | 易测试、易推理 |
| **不可变数据** | 数据一旦创建就不变 | 无副作用、线程安全 |
| **高阶函数** | 函数可以作为参数和返回值 | 代码复用、灵活组合 |
| **无副作用** | 函数不修改外部状态 | 可预测、易调试 |
**代表语言**Haskell, Lisp, Erlang, F#
### 2.4 声明式编程(Declarative
**核心思想**:告诉计算机"做什么",而不是"怎么做"
```sql
-- 查询所有活跃用户
SELECT name, email
FROM users
WHERE active = true
ORDER BY created_at DESC
```
**对比命令式**
| 命令式 | 声明式 |
|--------|--------|
| "从第一行开始遍历..." | "给我所有活跃用户" |
| "检查每个用户是否活跃..." | "按创建时间排序" |
| "如果活跃就加入结果..." | 数据库自己决定怎么执行 |
| "最后排序返回..." | |
**代表语言**SQL, Prolog, HTML
---
## 3. 类型系统:数据的分类规则
::: tip 💡 什么是类型系统?
类型系统是编程语言的**交通规则**,规定数据如何分类和操作。
就像现实世界:
- **整数** = 整数类型(1, 2, 3...
- **文字** = 字符串类型("hello"
- **是/否** = 布尔类型(true/false
:::
### 3.1 静态类型 vs 动态类型
| 特性 | 静态类型 | 动态类型 |
|------|---------|---------|
| **类型检查时机** | 编译时 | 运行时 |
| **代码示例** | `int x = 1;` | `x = 1` |
| **错误发现** | 编译期就发现 | 运行时才发现 |
| **灵活性** | 较低 | 较高 |
| **性能** | 较高(编译优化) | 较低(运行时检查) |
| **代表语言** | Java, C++, Rust, TypeScript | Python, JavaScript, Ruby |
**静态类型示例(Java**
```java
String name = "Alice";
name = 123; // 编译错误!类型不匹配
```
**动态类型示例(Python**
```python
name = "Alice"
name = 123 # 没问题,运行时类型改变
```
### 3.2 强类型 vs 弱类型
| 特性 | 强类型 | 弱类型 |
|------|--------|--------|
| **类型转换** | 不允许隐式转换 | 允许隐式转换 |
| **类型安全** | 高 | 低 |
| **代码示例** | `"1" + 1` 报错 | `"1" + 1 = "11"` |
| **代表语言** | Python, Java, Rust | JavaScript, PHP, C |
**弱类型示例(JavaScript**
```javascript
console.log("1" + 1) // "11" (字符串拼接)
console.log("1" - 1) // 0 (自动转数字)
console.log([] + []) // "" (空字符串)
console.log([] + {}) // "[object Object]"
```
**强类型示例(Python**
```python
"1" + 1 # TypeError: can only concatenate str to str
```
### 3.3 类型推断
现代语言可以**自动推断**变量类型:
```typescript
// TypeScript
let x = 1; // 推断为 number
let y = "hello"; // 推断为 string
// Rust
let x = 1; // 推断为 i32
let y = "hello"; // 推断为 &str
```
---
## 4. 编译型 vs 解释型
::: tip 💡 程序如何运行?
编程语言写的代码需要转换成机器能理解的指令,有两种主要方式:
:::
### 4.1 编译型语言
**流程**:源代码 → 编译器 → 机器码 → 执行
```
源代码 (main.c)
编译器 (gcc)
可执行文件 (main.exe)
CPU 直接执行
```
**特点**
| 优点 | 缺点 |
|------|------|
| 执行速度快 | 编译时间长 |
| 编译时发现错误 | 跨平台需要重新编译 |
| 不需要运行时环境 | 调试较困难 |
**代表语言**C, C++, Rust, Go
### 4.2 解释型语言
**流程**:源代码 → 解释器 → 逐行执行
```
源代码 (main.py)
解释器 (python)
逐行解释执行
```
**特点**
| 优点 | 缺点 |
|------|------|
| 跨平台 | 执行速度慢 |
| 开发调试快 | 运行时才能发现错误 |
| 代码即运行 | 需要解释器环境 |
**代表语言**Python, JavaScript, Ruby, PHP
### 4.3 混合型语言(JIT
**即时编译(Just-In-Time**:先解释执行,热点代码编译成机器码
```
源代码
字节码(中间代码)
解释执行 + JIT 编译热点代码
执行
```
**代表语言**Java, JavaScript (V8), Python (PyPy)
---
## 5. 如何选择编程语言?
::: tip 💡 没有最好的语言,只有最适合的语言
选择语言要考虑:
1. **问题领域**Web 开发?系统编程?数据分析?
2. **团队熟悉度**:团队擅长什么?
3. **生态系统**:有没有现成的库?
4. **性能需求**:需要多高的性能?
5. **开发效率**:需要多快开发完成?
:::
### 5.1 按应用场景选择
| 场景 | 推荐语言 | 原因 |
|------|---------|------|
| **Web 前端** | JavaScript, TypeScript | 浏览器原生支持 |
| **Web 后端** | Java, Go, Python, Node.js | 生态成熟,框架丰富 |
| **移动开发** | Swift (iOS), Kotlin (Android) | 官方推荐 |
| **数据分析** | Python, R | 库丰富,社区活跃 |
| **人工智能** | Python | TensorFlow, PyTorch |
| **系统编程** | C, C++, Rust | 性能高,控制精细 |
| **游戏开发** | C++, C#, Lua | 引擎支持 |
| **嵌入式** | C, Rust | 资源受限环境 |
| **云原生** | Go, Rust | 并发友好,部署简单 |
### 5.2 学习路线建议
**初学者**
1. Python(语法简单,应用广泛)
2. JavaScriptWeb 开发必备)
3. 选择一门静态类型语言(Java 或 TypeScript
**进阶**
1. 学习 C 理解底层
2. 学习函数式编程思想(Haskell 或 F#)
3. 学习 Rust 理解内存安全
---
## 6. 总结
::: tip 📚 核心要点
1. **编程语言演化**:从机器语言到高级语言,越来越接近人类思维
2. **编程范式**:命令式、面向对象、函数式、声明式,各有优劣
3. **类型系统**:静态/动态、强/弱类型,影响代码安全和灵活性
4. **运行方式**:编译型快但需编译,解释型慢但灵活
5. **选择语言**:没有银弹,根据场景选择合适的工具
:::
**下一步学习**
- [类型系统与编译原理入门](./type-systems-compilers) - 深入理解类型系统和编译过程
- [数据结构](./data-structures) - 理解数据的组织方式
- [算法思维入门](./algorithm-thinking) - 学习解决问题的方法
@@ -1,3 +1,259 @@
# 从晶体管到 CPU
> 待实现
::: tip 🎯 核心问题
**计算机是怎么"思考"的?** 你可能知道 CPU 是电脑的"大脑",但这个大脑到底是怎么工作的?它怎么从一堆金属和塑料变成能执行程序、处理数据的智能设备?本章带你从最底层的晶体管开始,一步步理解 CPU 的构造原理。
:::
---
## 0. 全景图:从沙子到智能
<TransistorDemo />
现代计算机的"思考"能力,归根结底来自于一个简单的东西:**开关**。
想象你有一个开关,可以控制灯的亮灭。现在,如果你有几十亿个这样的开关,并且能用它们组合出各种复杂的逻辑,会发生什么?这就是计算机的奥秘。
**从沙子到智能的层次结构:**
| 层级 | 名称 | 数量级 | 作用 | 类比 |
|------|------|--------|------|------|
| **1** | 晶体管 | 数十亿 | 最基本的开关单元 | 一个开关 |
| **2** | 逻辑门 | 数亿 | 实现基本逻辑运算 | 开关组合 |
| **3** | 功能单元 | 数百 | 实现特定功能(加法、存储等) | 功能模块 |
| **4** | CPU 核心 | 1-128 | 完整的处理器 | 大脑 |
::: tip 📊 逐行解读这张表
**第1层(晶体管)**:这是最底层的"开关"。现代 CPU 使用的是 MOSFET(金属氧化物半导体场效应晶体管),它的特点是:给栅极加电压,源极和漏极之间就导通;不加电压,就断开。这就是"用电控制电"的开关。
**第2层(逻辑门)**:把晶体管组合起来,就能实现"与"、"或"、"非"等逻辑运算。比如 AND 门:两个输入都为 1 时输出才为 1。这就像两个串联的开关,必须都按下灯才会亮。
**第3层(功能单元)**:把逻辑门组合起来,就能实现更复杂的功能。加法器能做加法,寄存器能存储数据,多路选择器能选择数据。这些是 CPU 的"器官"。
**第4层(CPU 核心)**:把功能单元组合起来,加上控制器、总线等,就形成了一个完整的 CPU 核心。它能取指令、解码、执行、写回结果——这就是"计算"的全部过程。
:::
---
## 1. 晶体管:数字世界的开关
### 1.1 什么是晶体管?
::: tip 💡 晶体管是什么?
**晶体管(Transistor** 是一种半导体器件,它可以像开关一样控制电流的通断。
**生活类比**:想象一个水龙头:
- **水龙头**:你用手拧开关,控制水流
- **晶体管**:用电压控制开关,控制电流
关键区别是:晶体管不是用手拧,而是用"电"来控制。这意味着一个开关可以控制另一个开关,从而实现"自动控制"。
:::
**晶体管的三个极:**
| 极 | 名称 | 作用 | 类比 |
|---|------|------|------|
| **源极 (Source)** | 电流入口 | 电流从这里进入 | 水管入口 |
| **漏极 (Drain)** | 电流出口 | 电流从这里流出 | 水管出口 |
| **栅极 (Gate)** | 控制端 | 控制是否导通 | 水龙头开关 |
### 1.2 晶体管如何表示 0 和 1?
计算机只认识 0 和 1,这和晶体管有什么关系?
::: tip 💡 用电压表示 0 和 1
**核心思想**:用电压的高低来表示 0 和 1。
- **高电压(如 3.3V**:表示 1
- **低电压(如 0V)**:表示 0
这就像灯泡的亮和灭:
- 灯亮 = 1
- 灯灭 = 0
晶体管的作用就是"控制灯泡的亮灭"——给栅极加高电压,源极和漏极导通,"灯泡"亮了(输出 1);给栅极低电压,源极和漏极断开,"灯泡"灭了(输出 0)。
:::
### 1.3 从一个开关到几十亿
你可能好奇:一个开关能做什么?答案是:一个开关做不了什么,但几十亿个开关组合起来,就能做任何计算。
**现代 CPU 的晶体管数量:**
| 年份 | CPU | 晶体管数量 | 制程工艺 |
|------|-----|-----------|---------|
| 1971 | Intel 4004 | 2,300 | 10μm |
| 1993 | Intel Pentium | 310万 | 0.8μm |
| 2006 | Intel Core 2 | 2.91亿 | 65nm |
| 2020 | Apple M1 | 160亿 | 5nm |
| 2023 | Apple M3 Max | 920亿 | 3nm |
::: tip 💡 什么是制程工艺?
**制程工艺**(如 5nm、3nm)指的是晶体管的尺寸。数字越小,晶体管越小,同样面积能容纳的晶体管越多。
- **5nm**:大约是 50 个原子的宽度
- **3nm**:大约是 30 个原子的宽度
制程越小,CPU 性能越强、功耗越低。但制造难度也指数级增加。
:::
---
## 2. 逻辑门:用开关做运算
### 2.1 从晶体管到逻辑门
一个晶体管只是一个开关,但把多个晶体管组合起来,就能实现"逻辑运算"。
<LogicGateDemo />
### 2.2 基本逻辑门详解
**AND 门(与门)**
- **规则**:两个输入都为 1,输出才为 1
- **生活类比**:串联的两个开关,必须都按下灯才亮
- **应用**:判断"多个条件是否同时满足"
**OR 门(或门)**
- **规则**:任一个输入为 1,输出就为 1
- **生活类比**:并联的两个开关,按任意一个灯就亮
- **应用**:判断"是否满足任一条件"
**NOT 门(非门)**
- **规则**:输入和输出相反
- **生活类比**:反相器,开变关、关变开
- **应用**:取反操作
**XOR 门(异或门)**
- **规则**:两个输入不同时输出 1
- **生活类比**:判断"两个值是否不同"
- **应用**:比较、加法运算
### 2.3 用逻辑门做加法
<AdderDemo />
::: tip 💡 加法器是怎么工作的?
**半加器**:处理两个 1 位二进制数相加
- 输入:A、B(各 1 位)
- 输出:和(S)、进位(C
- 公式:S = A XOR BC = A AND B
**全加器**:处理两个 1 位二进制数相加,加上上一位的进位
- 输入:A、B、Cin(进位输入)
- 输出:和(S)、Cout(进位输出)
**多位加法器**:把多个全加器级联起来
- 第 1 位加法器的进位输出,连接到第 2 位加法器的进位输入
- 就像我们手算加法时"逢二进一"
:::
---
## 3. 功能单元:逻辑门的组合
### 3.1 常见功能单元
| 单元 | 功能 | 组成 | 类比 |
|------|------|------|------|
| **加法器** | 做加法 | 多个全加器级联 | 计算器的加法功能 |
| **多路选择器** | 选择数据 | AND 门 + OR 门 | 多选一开关 |
| **译码器** | 解码指令 | 多个 AND 门 | 翻译器 |
| **寄存器** | 存储数据 | 触发器(锁存器) | 临时笔记本 |
| **计数器** | 计数 | 触发器级联 | 计分牌 |
### 3.2 寄存器:存储 1 位数据
::: tip 💡 寄存器是怎么存储数据的?
寄存器使用**触发器**电路来存储数据。触发器的特点是:一旦设置了状态,就能保持住,直到下一次改变。
**生活类比**:想象一个跷跷板:
- 推一下左边,左边就沉下去,右边翘起来
- 即使你松手,跷跷板也会保持这个状态
- 只有再推一下,才会改变状态
触发器就是这样的"电子跷跷板",能"记住"上一次被设置的状态。
:::
---
## 4. CPU 架构:从功能单元到处理器
### 4.1 CPU 的核心组件
<CpuArchitectureDemo />
### 4.2 CPU 是如何执行指令的?
CPU 执行一条指令,需要经过四个阶段:
| 阶段 | 名称 | 做什么 | 类比 |
|------|------|--------|------|
| **1** | 取指 (Fetch) | 从内存读取指令 | 从书架上取书 |
| **2** | 解码 (Decode) | 分析指令要做什么 | 阅读书的内容 |
| **3** | 执行 (Execute) | 执行运算 | 按书中的指示行动 |
| **4** | 写回 (Write Back) | 把结果存回寄存器 | 把结果记在笔记本上 |
::: tip 💡 指令周期
这四个阶段组成一个**指令周期**。CPU 不断重复这个周期,一条一条执行指令,就实现了"计算"。
现代 CPU 使用**流水线技术**,让多个指令的不同阶段并行执行:
- 第 1 条指令在执行时
- 第 2 条指令在解码
- 第 3 条指令在取指
这就像工厂流水线,大大提高了效率。
:::
### 4.3 CPU 性能的关键指标
| 指标 | 含义 | 影响 | 典型值 |
|------|------|------|--------|
| **主频** | 每秒执行多少个时钟周期 | 主频越高,执行越快 | 3-5 GHz |
| **核心数** | 独立的处理器数量 | 核心越多,并行能力越强 | 4-64 核 |
| **缓存** | CPU 内部的高速存储 | 缓存越大,访问内存越少 | 8-64 MB |
| **指令集** | CPU 能理解的指令集合 | 决定兼容性和功能 | x86、ARM |
---
## 5. 总结:从沙子到智能
让我们回顾一下从晶体管到 CPU 的完整路径:
```
沙子(硅)
↓ 提纯、切割
硅晶圆
↓ 光刻、蚀刻、掺杂
晶体管(开关)
↓ 组合
逻辑门(AND、OR、NOT...
↓ 组合
功能单元(加法器、寄存器...
↓ 组合
CPU 核心(ALU、控制器、寄存器组...)
↓ 编程
软件应用
```
::: tip 💡 核心启示
**计算机的本质是"开关的组合"**
- 一个开关做不了什么
- 但几十亿个开关,按特定方式组合,就能执行任何计算
- 这就是"量变引起质变"的最好例证
理解这一点,你就会明白:
- 为什么计算机只认识 0 和 1
- 为什么编程语言最终都要翻译成机器码
- 为什么算法效率如此重要(因为每一步操作都需要大量晶体管参与)
:::
---
## 延伸阅读
- **计算机组成原理**:深入了解 CPU、内存、I/O 的工作原理
- **数字电路**:学习逻辑门、触发器、时序电路的设计
- **计算机体系结构**:研究 CPU 的性能优化、流水线、缓存等
- **汇编语言**:直接和 CPU 对话,理解指令执行过程
@@ -1,3 +1,478 @@
# 类型系统与编译原理入门
> 待实现
::: tip 🎯 核心问题
**编程语言如何理解你的代码?** 当你写下 `int x = 10 + 5;` 时,编译器需要理解每个字符的含义、检查类型是否正确、优化代码、最终生成机器能执行的指令。本章带你理解这个神奇的过程。
:::
---
## 0. 想象你在翻译一本书:
- **识别单词**:把句子拆成一个个单词(词法分析)
- **理解语法**:判断句子是否符合语法规则(语法分析)
- **理解含义**:确保句子意思正确(语义分析)
- **优化表达**:让句子更简洁(代码优化)
- **翻译输出**:翻译成目标语言(代码生成)
**编译器就是编程语言的"翻译官"**,将人类可读的代码转换为机器可执行的指令。
<TypeSystemDemo />
---
## 1. 类型系统基础
### 1.1 什么是类型?
::: tip 💡 类型的本质
类型是对数据的**分类**,规定了数据可以进行的操作。
就像现实世界:
- **整数**:可以加减乘除,但不能分割
- **字符串**:可以拼接、截取,但不能直接运算
- **布尔**:只有 true/false,用于逻辑判断
:::
**基本数据类型**
| 类型 | 表示 | 占用空间 | 取值范围 |
|------|------|---------|---------|
| **整数** | int | 4 字节 | -2^31 到 2^31-1 |
| **浮点数** | float | 4 字节 | 约 ±3.4 × 10^38 |
| **双精度** | double | 8 字节 | 约 ±1.8 × 10^308 |
| **字符** | char | 1 字节 | 0 到 255 |
| **布尔** | bool | 1 字节 | true/false |
### 1.2 静态类型 vs 动态类型
::: tip 💡 核心区别
**静态类型**:变量类型在**编译时**确定
**动态类型**:变量类型在**运行时**确定
:::
**静态类型示例(Java**
```java
String name = "Alice"; // 编译时确定 name 是 String 类型
name = 123; // 编译错误!类型不匹配
```
**动态类型示例(Python**
```python
name = "Alice" # 运行时 name 是 str 类型
name = 123 # 运行时 name 变成 int 类型
print(type(name)) # <class 'int'>
```
**对比分析**
| 特性 | 静态类型 | 动态类型 |
|------|---------|---------|
| **类型检查时机** | 编译时 | 运行时 |
| **错误发现** | 早(编译期) | 晚(运行时) |
| **代码灵活性** | 低 | 高 |
| **执行性能** | 高(编译优化) | 低(运行时检查) |
| **IDE 支持** | 好(自动补全) | 差(运行时才知道类型) |
| **代表语言** | Java, C++, Rust, TypeScript | Python, JavaScript, Ruby |
### 1.3 强类型 vs 弱类型
::: tip 💡 核心区别
**强类型**:不允许隐式类型转换
**弱类型**:允许隐式类型转换
:::
**弱类型示例(JavaScript**
```javascript
console.log("1" + 1) // "11" - 字符串拼接
console.log("1" - 1) // 0 - 自动转数字
console.log([] + []) // "" - 空数组转空字符串
console.log(true + 1) // 2 - 布尔转数字
```
**强类型示例(Python**
```python
"1" + 1 # TypeError: can only concatenate str to str
"1" - 1 # TypeError: unsupported operand type(s)
```
**类型系统四象限**
| | 强类型 | 弱类型 |
|---|--------|--------|
| **静态** | Java, Rust, Haskell | C, C++ |
| **动态** | Python, Ruby | JavaScript, PHP |
### 1.4 类型推断
现代语言可以**自动推断**变量类型,结合静态类型的安全性和动态类型的简洁性:
```typescript
// TypeScript
let x = 1; // 推断为 number
let arr = [1, 2, 3]; // 推断为 number[]
let fn = (x) => x; // 推断为 (x: any) => any
// Rust
let x = 1; // 推断为 i32
let s = "hello"; // 推断为 &str
let v = vec![1, 2]; // 推断为 Vec<i32>
```
---
## 2. 编译原理基础
### 2.1 编译器的任务
::: tip 💡 编译器做什么?
编译器将**源代码**转换为**目标代码**,主要完成:
1. **理解代码**:分析源代码的结构和含义
2. **检查正确性**:发现语法和语义错误
3. **优化代码**:提高执行效率
4. **生成代码**:输出目标机器的指令
:::
<CompilerDemo />
### 2.2 词法分析(Lexical Analysis
**任务**:将源代码分解为**词法单元(Token)**
**示例**
```
源代码: int x = 10 + 5;
词法单元:
[int] → 关键字
[x] → 标识符
[=] → 运算符
[10] → 整数字面量
[+] → 运算符
[5] → 整数字面量
[;] → 分隔符
```
**词法分析器的工作**
| 输入 | 处理 | 输出 |
|------|------|------|
| `int` | 匹配关键字表 | `KEYWORD(int)` |
| `x` | 匹配标识符规则 | `IDENTIFIER(x)` |
| `10` | 匹配数字规则 | `NUMBER(10)` |
### 2.3 语法分析(Syntax Analysis
**任务**:根据语法规则,将 Token 流组织成**语法树(AST**
**示例**
```
表达式: 1 + 2 * 3
语法树:
+
/ \
1 *
/ \
2 3
```
::: tip 💡 为什么是这棵树?
根据运算优先级,`*` 优先级高于 `+`,所以 `2 * 3` 先结合。
如果表达式是 `(1 + 2) * 3`,语法树会变成:
```
*
/ \
+ 3
/ \
1 2
```
:::
**语法规则(文法)**
```
表达式 → 表达式 + 项 | 表达式 - 项 | 项
项 → 项 * 因子 | 项 / 因子 | 因子
因子 → 数字 | (表达式)
```
### 2.4 语义分析(Semantic Analysis
**任务**:检查语义正确性,进行类型检查
**主要工作**
| 工作 | 说明 | 示例 |
|------|------|------|
| **类型检查** | 检查类型是否匹配 | `int x = "hello";` → 错误 |
| **作用域分析** | 检查变量是否声明 | 使用未声明变量 → 错误 |
| **符号表构建** | 记录所有标识符信息 | 变量名、类型、作用域 |
| **类型推断** | 推断表达式类型 | `1 + 2.0` → float |
**符号表示例**
```
int x = 10;
float y = 3.14;
string name = "Alice";
符号表:
┌──────────┬────────┬─────────┐
│ 名称 │ 类型 │ 作用域 │
├──────────┼────────┼─────────┤
│ x │ int │ global │
│ y │ float │ global │
│ name │ string │ global │
└──────────┴────────┴─────────┘
```
### 2.5 中间代码生成
**任务**:生成平台无关的中间表示(IR
**三地址码示例**
```
源代码: int x = (a + b) * c;
三地址码:
t1 = a + b
t2 = t1 * c
x = t2
```
::: tip 💡 为什么需要中间代码?
1. **平台无关**:一次编写,多平台编译
2. **便于优化**:在 IR 层面进行优化
3. **支持多语言**:不同语言可以编译到同一 IR
例如 LLVM IR 支持 C、C++、Rust、Swift 等多种语言。
:::
### 2.6 代码优化
**任务**:提高代码执行效率
**常见优化技术**
| 优化技术 | 说明 | 示例 |
|---------|------|------|
| **常量折叠** | 编译时计算常量表达式 | `10 + 5``15` |
| **死代码消除** | 删除不会执行的代码 | `if (false) { ... }` → 删除 |
| **内联展开** | 函数调用替换为函数体 | `add(1, 2)``1 + 2` |
| **循环优化** | 减少循环开销 | 循环展开、循环不变量外提 |
| **公共子表达式消除** | 避免重复计算 | `a+b` 计算一次,多次使用 |
**优化示例**
```c
// 优化前
int x = 10 + 5; // 常量折叠
int y = x * 2; // x 已知为 15
if (false) { // 死代码
printf("never");
}
// 优化后
int x = 15;
int y = 30;
// if 语句被删除
```
### 2.7 目标代码生成
**任务**:生成目标机器的机器码
**汇编代码示例**
```asm
; int x = 15;
mov eax, 15
mov dword ptr [x], eax
; int y = 30;
mov eax, 30
mov dword ptr [y], eax
```
**代码生成的主要任务**
| 任务 | 说明 |
|------|------|
| **指令选择** | 选择合适的机器指令 |
| **寄存器分配** | 决定哪些变量放在寄存器 |
| **指令调度** | 安排指令顺序,提高流水线效率 |
---
## 3. 编译型 vs 解释型 vs JIT
### 3.1 编译型语言
**流程**:源代码 → 编译器 → 机器码 → 执行
```
main.c → [编译器] → main.exe → [CPU] → 执行
```
**特点**
- ✅ 执行速度快
- ✅ 编译期发现错误
- ❌ 编译时间长
- ❌ 跨平台需要重新编译
**代表语言**C, C++, Rust, Go
### 3.2 解释型语言
**流程**:源代码 → 解释器 → 逐行执行
```
main.py → [解释器] → 逐行解释执行
```
**特点**
- ✅ 跨平台
- ✅ 开发调试快
- ❌ 执行速度慢
- ❌ 运行时才能发现错误
**代表语言**Python, Ruby, PHP
### 3.3 JIT(即时编译)
**流程**:源代码 → 字节码 → JIT 编译 → 执行
```
源代码 → [编译器] → 字节码 → [JIT] → 机器码 → 执行
```
**工作原理**
1. 先将源代码编译成字节码(中间代码)
2. 解释器逐行执行字节码
3. 发现热点代码(频繁执行),JIT 编译成机器码
4. 后续直接执行机器码
**特点**
- ✅ 兼顾性能和跨平台
- ✅ 热点代码执行快
- ❌ 启动慢(需要预热)
- ❌ 内存占用大
**代表语言**Java (JVM), JavaScript (V8), Python (PyPy)
---
## 4. 实践:手写简单解释器
### 4.1 目标
实现一个简单的计算器,支持加减乘除:
```
输入: 1 + 2 * 3
输出: 7
```
### 4.2 词法分析器
```python
import re
Token = namedtuple('Token', ['type', 'value'])
def tokenize(code):
tokens = []
for match in re.finditer(r'\d+|[+\-*/()]', code):
value = match.group()
if value.isdigit():
tokens.append(Token('NUMBER', int(value)))
else:
tokens.append(Token(value, value))
return tokens
# 测试
print(tokenize('1 + 2 * 3'))
# [Token(type='NUMBER', value=1), Token(type='+', value='+'), ...]
```
### 4.3 语法分析器
```python
class Parser:
def __init__(self, tokens):
self.tokens = tokens
self.pos = 0
def parse(self):
return self.expr()
def expr(self):
result = self.term()
while self.current() in ('+', '-'):
op = self.consume()
right = self.term()
if op == '+':
result += right
else:
result -= right
return result
def term(self):
result = self.factor()
while self.current() in ('*', '/'):
op = self.consume()
right = self.factor()
if op == '*':
result *= right
else:
result //= right
return result
def factor(self):
token = self.consume()
if token.type == 'NUMBER':
return token.value
elif token.value == '(':
result = self.expr()
self.consume() # )
return result
```
### 4.4 完整解释器
```python
def evaluate(code):
tokens = tokenize(code)
parser = Parser(tokens)
return parser.parse()
print(evaluate('1 + 2 * 3')) # 7
print(evaluate('(1 + 2) * 3')) # 9
print(evaluate('10 - 2 * 3')) # 4
```
---
## 5. 总结
::: tip 📚 核心要点
1. **类型系统**:静态/动态、强/弱类型,影响代码安全和灵活性
2. **编译流程**:词法分析 → 语法分析 → 语义分析 → 中间代码 → 优化 → 代码生成
3. **执行方式**:编译型快但需编译,解释型慢但灵活,JIT 兼顾两者
4. **实践价值**:理解编译原理有助于写出更好的代码
:::
**下一步学习**
- [编程语言图谱](./programming-languages) - 了解更多编程语言
- [数据结构](./data-structures) - 理解数据的组织方式
- [算法思维入门](./algorithm-thinking) - 学习解决问题的方法