数据结构与算法-栈结构
一、前言
1.1.什么是数据结构?
数据结构就是在计算机中,存储和组织数据的方式。
例如:图书管理,怎样摆放图书才能既能放很多书,也方便取?
主要需要考虑两个问题:
操作一:新书怎么插入?
操作二:怎么找到某本指定的书?
常见的数据结构:
- 数组(Aarray)
- 栈(Stack)
- 链表(Linked List)
- 图(Graph)
- 散列表(Hash)
- 队列(Queue)
- 树(Tree)
- 堆(Heap)
注意:数据结构与算法与语言无关,常见的编程语言都有直接或间接的使用上述常见的数据结构。
1.2.什么是算法?
算法(Algorithm)的定义
一个有限指令集,每条指令的描述不依赖于语言;
接收一些输入(有些情况下不需要输入);
产生输入;
一定在有限步骤之后终止;
算法通俗理解:解决问题的办法/步骤逻辑。数据结构的实现,离不开算法。
二、栈(Stack)
2.1栈简介
数组是一个线性结构,并且可以在数组的任意位置插入和删除元素。而栈和队列就是比较常见的受限的线性结构。如下图所示:
栈的特点为先进后出,后进先出(LIFO:last in first out)。
程序中的栈结构:
- 函数调用栈:A(B(C(D()))):即A函数中调用B,B调用C,C调用D;在A执行的过程中会将A压入栈,随后B执行时B也被压入栈,函数C和D执行时也会被压入栈。所以当前栈的顺序为:A->B->C->D(栈顶);函数D执行完之后,会弹出栈被释放,弹出栈的顺序为D->C->B->A;
- 递归:为什么没有停止条件的递归会造成栈溢出?比如函数A为递归函数,不断地调用自己(因为函数还没有执行完,不会把函数弹出栈),不停地把相同的函数A压入栈,最后造成栈溢出(Stack
Overfloat)
栈常见的操作:
- push(element):添加一个新元素到栈顶位置;
- pop():移除栈顶的元素,同时返回被移除的元素;
- peek():返回栈顶的元素,不对栈做任何修改(该方法不会移除栈顶的元素,仅仅返回它);
- isEmpty():如果栈里没有任何元素就返回true,否则返回false;
- size():返回栈里的元素个数。这个方法和数组的length属性类似;
- toString():将栈结构的内容以字符串的形式返回。
2.2基于数组封装栈结构
function Stack(){
this.items = [];
// 1、入栈
Stack.prototype.push = function(item){
this.items.push(item);
}
// 2、出栈
Stack.prototype.pop = function(){
return this.items.pop();
}
// 3、查看栈顶元素
Stack.prototype.peek = function(){
return this.items[this.items.length - 1];
}
// 4、判断是否为空
Stack.prototype.isEmpty = function(){
return this.items.length === 0;
}
// 5、获取栈中元素个数
Stack.prototype.count = function(){
return this.items.length;
}
// 6、toString方法
Stack.prototype.toString = function(){
let str = '';
for (var i = 0; i < this.items.length; i++) {
str += this.items[i]+" ";
}
return str;
}
}
let mystack = new Stack();
mystack.push(20);
mystack.push(10);
mystack.push(40);
mystack.push(60);
mystack.push(90);
console.log(mystack.toString());
console.log("出栈",mystack.pop());
mystack.pop();
console.log(mystack.toString());
console.log(mystack.isEmpty());
console.log(mystack.count());
console.log(mystack.peek());
应用:十进制转二进制
注意该代码中的Stack就是上面实现的栈结构
// 循环写法
function getBinByWhile(dCode){
let mStack = new Stack();
while(dCode > 0){
mStack.push(dCode % 2);
dCode = Math.floor(dCode / 2);
}
return mStack.allPop();
}
console.log("getBinByWhile",getBinByWhile(200));
// 递归写法
function getBin(dCode,mStack){
console.log("------------",mStack);
if( dCode < 1 ){
mStack.push(0);
return
}
mStack.push(dCode % 2);
getBin(Math.floor(dCode / 2),mStack);
}
let mystack = new Stack();
getBin(1000,mystack);
console.log(mystack.allPop());
console.log(Math.floor(0/2));
2.3基于链表封装栈结构
注意:链表在下篇文章会详细介绍此处直接撸出来了
/**
* 基于链表的栈结构
*
* */
//链表类
function LinkList(){
function Node(data){
this.data = data;
this.next = null;
}
this.head = null;
this.length = 0;
//添加数据
LinkList.prototype.append = function (data){
//创建新节点
let newNode = new Node(data);
if (this.head === null){
this.head = newNode;
}else{
let current = this.head;
while (current.next){
current = current.next;
}
current.next = newNode;
}
this.length += 1;
}
//向指定位置插入数据
LinkList.prototype.insert = function (data,index){
let newNode = new Node(data);
let current = this.head;
if (index === 0){
//插入首位时
this.head = newNode;
newNode.next = current;
}else if (index <= this.length && index >= 0 ){
for (let i = 1; i < index; i++) {
current = current.next;
}
newNode.next = current.next;
current.next = newNode;
}else {
console.log("该节点不存在")
}
this.length += 1;
}
//根据下标获得数据
LinkList.prototype.get = function (index){
if (index === this.length){
return "链表没那么长";
}
let current = this.head;
for (let i = 0; i < index; i++) {
current = current.next;
}
return current.data;
}
//获得元素下标
LinkList.prototype.indexOf = function (data){
let current = this.head;
let index = 0;
let is = true;
while (current.data !== data){
index++;
current = current.next;
if (current === null){
is = false;
break;
}
}
if (!is){
return false;
}
return index;
}
//更新数据(根据下标)
LinkList.prototype.update = function (newData,index){
let current = this.head;
if (index <= this.length && index >= 0 ){
for (let i = 0; i < index; i++) {
current = current.next;
}
current.data = newData;
}else {
console.log("该节点不存在")
}
}
//移除数据(根据指定下标)
LinkList.prototype.removeAt = function (index){
let current = this.head;
let last = null;
let res = null;
if (index === 0){
res = current.data;
index === this.length -1 ? this.head = null : this.head = current.next;
this.length--;
return res;
}else if (index > 0 && index <= this.length-1){
for (let i = 0; i < index; i++) {
if (i === index -1){
last = current;
}
current = current.next;
}
res = current.data;
index === this.length -1 ? last.next = null : last.next = current.next;
this.length--;
return res;
}else {
console.log("该下标不存在")
}
}
//移除数据(根据指定元素)
LinkList.prototype.remove = function (data){
return this.removeAt(this.indexOf(data));
}
//isEmpty
LinkList.prototype.isEmpty = function (){
return this.length === 0;
}
//toString
LinkList.prototype.toString = function (){
let current = this.head;
let str = '';
while (current){
str += current.data+" ";
current = current.next;//指针下移
}
return str;
}
}
/**
* 栈
* */
function Stack(){
this.items = new LinkList();
//添加进栈
Stack.prototype.push = function (data){
this.items.append(data);
}
//出栈
Stack.prototype.pop = function (){
return this.items.removeAt(this.items.length - 1);
}
//查看栈顶元素
Stack.prototype.peek = function (){
return this.items.get(this.items.length - 1);
}
//栈大小
Stack.prototype.size = function (){
return this.items.length
}
//是否为空
Stack.prototype.isEmpty = function (){
return this.items.length === 0
}
//toString
Stack.prototype.toString = function (){
return this.items.toString();
}
}
let stack = new Stack();
stack.push('yxh');
stack.push(666);
stack.push(false);
stack.push("哈哈哈");
//
// console.log(stack.peek());
console.log(stack.pop());
console.log(stack.toString());
console.log(stack.pop());
console.log(stack.toString());
console.log(stack.pop());
console.log(stack.toString());
console.log(stack.pop());
console.log(stack.toString());
应用:十进制转二进制
注意该代码中的Stack就是上面实现的栈结构
function dec_bin(code){
let stack = new Stack();
let str = "";
while (code > 0){
stack.push(code % 2);
code = Math.floor(code / 2);
}
console.log(stack.toString())
console.log(stack.size())
let length = stack.size();
for (let i = 0; i < length; i++) {
str += stack.pop();
}
return str;
}
console.log(dec_bin(100));
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~