js数据结构与算法

js数据结构与算法

1.栈

栈是一种遵从后进先出(LIFO)原则的有序集合。新添加的或待删除的元素都保存在栈的 同一端,称作栈顶,另一端就叫栈底。在栈里,新元素都靠近栈顶,旧元素都接近栈底。

//栈
        function Stack() {
        //各种属性和方法的声明
            let items = [];
            //添加元素
            this.push = function(element){
                items.push(element);
            };
            //移除元素
            this.pop = function(){
                return items.pop();
            };
            //查看栈顶
            this.peek = function(){
                return items[items.length-1];
            }; 
            //查看栈是不是为空
            this.isEmpty = function(){
                return items.length == 0;
            }; 
            //清空栈元素
            this.clear = function(){
                items = [];
            };
            //打印栈元素
            this.print = function(){
                console.log(items.toString());
            }; 
        }

2.队列

队列是遵循FIFO(First In First Out,先进先出,也称为先来先服务)原则的一组有序的项。 队列在尾部添加新元素,并从顶部移除元素。最新添加的元素必须排在队列的末尾。

//队列
        function Queue() {
            //这里是属性和方法
            let items = [];
            //添加元素
            this.enqueue = function(element){
                items.push(element);
            }; 
            //移除元素
            this.dequeue = function(){
                return items.shift();//前删
            };
            //查看队头
            this.front = function(){
                return items[0];
            };
            //检查是否为空
            this.isEmpty = function(){
                return items.length == 0;
            }; 
            //打印队列
            this.print = function(){
                console.log(items.toString());
            }; 
            //队列的长度
            this.size = function(){
                return items.length
            }; 
        } 

2.1优先队列

​ 队列大量应用在计算机科学以及我们的生活中,我们在之前话题中实现的默认队列也有一些 修改版本。 其中一个修改版就是优先队列。元素的添加和移除是基于优先级的。一个现实的例子就是机 场登机的顺序。

​ 头等舱和商务舱乘客的优先级要高于经济舱乘客。在有些国家,老年人和孕妇(或 带小孩的妇女)登机时也享有高于其他乘客的优先级。

​ 另一个现实中的例子是医院的(急诊科)候诊室。医生会优先处理病情比较严重的患者。通 常,护士会鉴别分类,根据患者病情的严重程度放号。

//优先队列
        function PriorityQueue() {
            let items = [];
            //构造函数
            function QueueElement (element, priority){ // {1}
                this.element = element;
                this.priority = priority;//优先级顺序
            }
            //添加元素
            this.enqueue = function(element, priority){
                let queueElement = new QueueElement(element, priority);
                let added = false;
                for (let i=0; i<items.length; i++){
                    if (queueElement.priority < items[i].priority){ // {2}
                        items.splice(i,0,queueElement); // {3}
                        added = true;
                        break; // {4}
                    }
                }
                if (!added){
                    items.push(queueElement); //{5}
                }
            };
            this.print = function(){
                for (let i=0; i<items.length; i++){
                    console.log(`${items[i].element} -
                    ${items[i].priority}`);
                }
            };
            //其他方法和默认的Queue实现相同
        } 

2.2击鼓传花

​ 还有另一个修改版的队列实现,就是循环队列。循环队列的一个例子就是击鼓传花游戏(Hot Potato)。在这个游戏中,孩子们围成一个圆圈,把花尽快地传递给旁边的人。某一时刻传花停止, 这个时候花在谁手里,谁就退出圆圈结束游戏。重复这个过程,直到只剩一个孩子(胜者)。

//击鼓传花
        function hotPotato (nameList, num){
            let queue = new Queue(); // {1}
            //把传过来的值放到队列中
            for (let i=0; i<nameList.length; i++){
                queue.enqueue(nameList[i]); // {2}
            }

            let eliminated = '';//被淘汰的人
            while (queue.size() > 1){ 
                for (let i=0; i<num-1; i++){
                    queue.enqueue(queue.dequeue()); // {3}
                }   
                eliminated = queue.dequeue();// {4}
                console.log(eliminated + '在击鼓传花游戏中被淘汰。');
            }
                return queue.dequeue();// {5}
        }
        let names = ['John','Jack','Camila','Ingrid','Carl'];
        let winner = hotPotato(names, 7);
        console.log('The winner is: ' + winner); 

3.链表

​ 链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个 元素由一个存储元素本身的节点和一个指向下一个元素的引用(也称指针或链接)组成。

//链表
        function LinkedList(){
            let Node = function(element){
                this.element = element;
                this.next = null;
            }
            this.length = 0;
            this.head = null;
            //添加元素
            LinkedList.prototype.append = function(element){
                let node = new Node(element);
                let current = null;
                if(this.length==0){
                    this.head = node
                }else{
                    current = this.head;
                    while(current.next){
                        current = current.next
                    }
                    current.next = node;
                }
                this.length++;
            }
            //打印链表
            LinkedList.prototype.toString = function (){
                let current = this.head;
                var listString = '';
                while(current){
                    listString += current.element+' ';
                    current = current.next
                }
                return listString
            }
            //插入元素
            LinkedList.prototype.insert = function (position,element){
                if(position<0 || position>this.length) return;
                let newNode = new Node(element);//创建一个新的节点
                let current = this.head;//记入当前的元素
                let previous = null;//记入上一个元素
                //current变量是对列表中第一个元素的引用。我们需要做的是把node.next的值设为
                //current(列表中第一个元素)。现在head和node.next都指向了current。接下来要做的就是
                //把head的引用改为node,这样列表中就有了一个新元素。
                if(position == 0){ 
                    node.next = current;
                    this.head = node;
                }else{
                //在列表中间或尾部添加一个元素。首先,我们需要循环访问列表,
				//找到目标位置(行{3})。当跳出循环时,current变量将是对想要插入新元素的位置之后一个
				//元素的引用,而previous将是对想要插入新元素的位置之前一个元素的引用。在这种情况下,
				//我们要在previous和current之间添加新项。因此,首先需要把新项(node)和当前项链接起
				//来(行{4}),然后需要改变previous和current之间的链接。我们还需要让previous.next
				//指向node(行{5})。
                    let index = 0;
                    while(index++ < position){
                        previous = current;
                        current = current.next;
                    }
                    newNode.next = current;//新节点的
                    previous.next = newNode;
                }
                this.length++; 
                return true;
            }
            //indexOf方法接收一个元素的值,如果在列表中找到它,就返回元素的位置,否则返回-1
            LinkedList.prototype.indexOf = function (element){
                let current = this.head;
                let index = 0;
                while(current){
                    if(element === current.element){
                        return index;
                    }
                    index++;
                    current = current.next;
                }
                return -1;
            }
             //移除元素通过下标
            LinkedList.prototype.removeAt = function (position){
                if(position<0 || position>this.length) return null;
                let current = this.head;
                let previous = null;
                let index = 0;
                //删除第一项
                if(position === 0){
                    this.head = current.next;
                }else{
                    while(index++ < position){
                        previous = current;
                        current = current.next;
                    }
                    //将previous与current的下一项链接起来:跳过current,从而移除它
                    previous.next = current.next;
                }
                this.length--;
                return current.element;
            }
            //移除元素
            LinkedList.prototype.remove = function(element){
                let index = this.indexOf(element);
                return this.removeAt(index);
            }; 
        }

4.双向链表

​ 双向链表也叫双链表,是链表的一种,它的每个数据结点中都有两个指针,分别指向直接后继和直接前驱。所以,从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双向循环链表。

 function DoubleLinkedList(){
            // 内部类
            function Node(element){
                this.prev = null;
                this.element = element;
                this.next = null
            }
            this.head = null;
            this.tail = null;
            this.length = 0;
            //追加元素
            DoubleLinkedList.prototype.append = function(element){
                let newNode = new Node(element)
                if(this.length === 0){
                    this.head = newNode;
                    this.tail = newNode;
                }else{
                    newNode.prev = this.tail;
                    this.tail.next = newNode;
                    this.tail = newNode
                }
                this.length++;
            }
            // 打印元素
            DoubleLinkedList.prototype.toString = function(){
                let current = this.head;
                let result = '';
                while(current){
                    result+=current.element+' ';
                    current = current.next;
                }
                return result
            }
            // 插入元素
            DoubleLinkedList.prototype.insert = function(element,postion){
                if(postion < 0 || postion > this.length) return false
                //新的节点
                let newNode = new Node(element);
                if(this.length === 0){
                    this.head = newNode;
                    this.tail = newNode;
                }else{
                    if(postion === 0){
                        this.head.prev = newNode;
                        newNode.next = this.head;
                        this.head = newNodw
                    }else if(postion === this.length){
                        newNode.prev = this.tail;
                        this.tail.next = newNode;
                        this.tail = newNode
                    }else{
                        let current = this.head;
                        let index = 0;
                        while(index++ < postion){
                            current = current.next
                        }
                        newNode.prev = current.prev;
                        newNode.next = current;
                        current.prev.next = newNode;
                        current.prev = newNode;
                    }
                }
                this.length++;
                return true
            }
        }
        let list = new DoubleLinkedList()
        list.append('aaa')
        list.append('bbb')
        list.append('ccc')
        console.log(list.insert('ddd',2))
        console.log(list.toString())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值