数据结构与算法-栈结构


一、前言

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));



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值