zoukankan      html  css  js  c++  java
  • 数据结构-链表<Typescript>

    链表

    什么是链表?

    链表是一种动态的数据结构,不同于数组的是,链表分配内存空间的灵活性,它不会像数组一样被分配一块连续的内存。当你想在数组的任意位置,插入一个
    新值的时候,必须对数组中的各个元素进行相应的位置移动才能达到目标,开销显然是很大的。然而链表的灵活性在于它的每个元素节点分为两部分,一部分
    是存储元素本身,另一部分是指向下一个节点元素的引用,也可以称为指针,当你要插入数据时,把上一个节点的向下指针指向新数据节点,新数据节点的向
    下指针指向原有数据。但是链表不像数组那样可以直接通过索引立刻定位,只能通过遍历。

     定义个node类

    /*节点*/
    class Node<T>{
        public element:T;//节点数据
        public next:Node<T> = null;//指向下一个节点 
        constructor(element:T){
            this.element = element;
        }
    }

    链表的实现

    class LinkList<T>{
        private head:Node<T> = null;//链表头
        private tail:Node<T> = null;//链表尾
        private length:number = 0;//链表长度
        /* 向链表添加新节点 */
        public append(element:T):void{
            let node:Node<T> = new Node<T>(element);
            if(this.length <= 0){//如果当前链表为空,则将head,tail指向node
                this.head = node;
                this.tail = node;
            }else{//否则在链表尾添加新元素
                this.tail.next = node;
                this.tail = node;
            }
            this.length++;//链表长度+1
        }
        /* 在链表某位置插入节点 */
        public insert(position:number,element:T):boolean{
            if(position < 1 || position > this.length + 1){
                return false;
            }
            let node:Node<T> = new Node<T>(element);
            if(position == 1){//如果插在第一个位置,将head指向该节点
                node.next = this.head;
                this.head = node;
                if(this.length == 0){
                    this.tail = node;
                }
            }else if(position == this.length + 1){//如果插在最后,将tail指向该节点
                this.tail.next = node;
                this.tail = node;
            }else{//剩余是插在链表中间
                let prevNode:Node<T> = this.getNodeAt(position - 1);
                let currentNode:Node<T> = prevNode.next;
                prevNode.next = node;
                node.next = currentNode;
            }
            this.length++;//链表长度+1
        }
        /* 查找某个元素所在的节点位置 */
        public positionOf(element:T):number{
            let currentNode:Node<T> = this.head;
            let currentPosition:number = 1;
            while(currentNode){
                if(currentNode.element == element){
                    return currentPosition;
                }
                currentPosition++;
                currentNode = currentNode.next;
            }
            return -1;
        }
        /* 删除某元素节点 */
        public remove(element:T):boolean{
            let position:number = this.positionOf(element);
            if(position < 1 || position > this.length){//越界
                return false;
            }
            let isSuccess:boolean = this.removeAt(position);
            return isSuccess;
        }
        /* 删除某个位置的节点 */
        public removeAt(position:number):boolean{
            if(position < 1 || position > this.length){//越界
                return false;
            }
            let currentNode:Node<T> = this.head;
            if(position == 1){//删除第一个节点
                this.head = currentNode.next;
                if(this.length == 1){
                    this.tail = null;
                }
            }else{
                let prevNode:Node<T> = this.getNodeAt(position - 1);
                prevNode.next = prevNode.next.next;
                if(position == this.length){
                    this.tail = prevNode;
                }
            }
            this.length--;//链表长度减一
            return true;
        }
        /*  返回某位置的节点*/
        public getNodeAt(position:number):Node<T>{
            if(position < 1 || position > this.length){//越界
                return null;
            }
            let currentNode:Node<T> = this.head;
            let currentPositon:number = 1;
            while(currentPositon < position){//遍历链表,找到节点
                currentNode = currentNode.next;
                currentPositon++;
            }
            return currentNode;
        }
        /* 链表是否为空 */
        public isEmpty():boolean{
            return this.length == 0;
        }
        /*  返回链表长度 */
        public size():number{
            return this.length;
        }
        /* 返回链表头 */
        public getHead():Node<T>{
            return this.head;
        }
        /* 返回链表尾 */
        public getTail():Node<T>{
            return this.tail;
        }
        /* 清空链表 */
        public clear():void{
            this.head = null;
            this.tail = null;
            this.length = 0;
        }
        /* 打印链表 */
        public print():string{
            let currentNode:Node<T> = this.head;
            let str:string = "";
            let currentPostion:number = 1;
            while(currentNode){
                if(currentPostion < this.length){
                    str += `element:${currentNode.element} ---- `;
                }else{
                    str += `element:${currentNode.element}`;
                }
                currentNode = currentNode.next;
                currentPostion++;
            }
            return str;
        }
    }

    测试

    let list:LinkList<string> = new LinkList<string>();
    list.append("电视剧");
    list.append("天地男儿");
    list.append("刑事侦缉档案");
    list.append("西游记");
    list.print();
    list.remove("电视剧");
    list.print();
    list.insert(1,"TVB");
    list.print();
    list.removeAt(2);
    list.print();

     双向链表

    上面链表称为单链表,每一个元素有一个next指针,指向下一个节点,我们只能从链表的头部开始遍历整个链表,任何一个节点只能找到它的下一个节点,
    而不能找到它的上一个节点。双向链表中的每一个元素拥有两个指针,一个用来指向下一个节点,一个用来指向上一个节点。在双向链表中,除了可以像
    单向链表一样从头部开始遍历之外,还可以从尾部进行遍历。

     //节点

    /* 节点 */
     class Node<T>{
        public element:T;
        public next:Node<T>;
        public prev:Node<T>;
        constructor(element:T){
            this.element = element;
        }
    }

    //实现

    /* 双向链表 */
    class DoubleList<T>{
        private length:number = 0;
        private head:Node<T> = null;
        private tail:Node<T> = null;
        /* 向链表添加元素为element的节点 */
        public append(element:T):void{
            let node:Node<T> = new Node<T>(element); 
            if(this.length <= 0){
                this.head = node;
                this.tail = node;
            }else{
                this.tail.next = node;
                node.prev = this.tail;
                this.tail = node;
            }
            this.length++;//链表长度+1
        }
        /* 在链表某位置插入节点 */
        public insert(position:number,element:T):boolean{
            if(position < 1 || position > this.length + 1){
                return false;
            }
            let node:Node<T> = new Node<T>(element);
            if(position == 1){//如果插在第一个位置,将head指向该节点
                node.next = this.head;
                this.head.prev = node;
                this.head = node;
                if(this.length == 0){
                    this.tail = node;
                }
            }else if(position == this.length + 1){//如果插在最后,将tail指向该节点
                this.tail.next = node;
                node.prev = this.tail;
                this.tail = node;
            }else{//剩余是插在链表中间
                let prevNode:Node<T> = this.getNodeAt(position - 1);
                let currentNode:Node<T> = prevNode.next;
                prevNode.next = node;
                node.prev = prevNode;
                node.next = currentNode;
                currentNode.prev = node;
            }
            this.length++;//链表长度+1
        }
        /* 查找某个元素所在的节点位置 */
        public positionOf(element:T):number{
            let currentNode:Node<T> = this.head;
            let currentPosition:number = 1;
            while(currentNode){
                if(currentNode.element == element){
                    return currentPosition;
                }
                currentPosition++;
                currentNode = currentNode.next;
            }
            return -1;
        } 
        /* 删除某元素节点 */
        public remove(element:T):boolean{
            let position:number = this.positionOf(element);
            if(position < 1 || position > this.length){//越界
                return false;
            }
            let isSuccess:boolean = this.removeAt(position);
            return isSuccess;
        }
        /* 删除某个位置的节点 */
        public removeAt(position:number):boolean{
            if(position < 1 || position > this.length){//越界
                return false;
            }
            let currentNode:Node<T> = this.head;
            let prevNode:Node<T>;
            if(position == 1){//删除第一个节点
                this.head = currentNode.next;
                if(this.head){
                    this.head.prev = null;
                }
                if(this.length == 1){
                    this.tail = null;
                }
            }else if(position == this.length){//删除最后一个节点
                prevNode = this.tail;
                prevNode.next = null;
                this.tail = prevNode;
            }else{
                prevNode = this.getNodeAt(position - 1);
                prevNode.next = prevNode.next.next;
                prevNode.next.prev = prevNode;
            }
            this.length--;//链表长度减一
            return true;
        }
        /* 返回某个位置的节点 */
        public getNodeAt(position:number):Node<T>{
            if(position < 1 || position > this.length){
                return null;
            }
            let currentNode:Node<T>;
            let currentPosition:number = 1;
            //从后往前遍历
            if(position > Math.floor(this.length / 2)){
                currentNode = this.tail;
                while(currentPosition < this.length - position + 1){
                    currentNode = currentNode.prev;
                    currentPosition++;
                }
                return currentNode;
            }else{//从前往后
                currentNode = this.head;
                while(currentPosition >= this.length){
                    currentNode = currentNode.prev;
                    currentPosition++;
                }
                return currentNode;
            }
        }
         /* 链表是否为空 */
         public isEmpty():boolean{
            return this.length == 0;
        }
        /*  返回链表长度 */
        public size():number{
            return this.length;
        }
        /* 返回链表头 */
        public getHead():Node<T>{
            return this.head;
        }
        /* 返回链表尾 */
        public getTail():Node<T>{
            return this.tail;
        }
        /* 清空链表 */
        public clear():void{
            this.head = null;
            this.tail = null;
            this.length = 0;
        }
        /* 打印链表 */
        public print():string{
            let currentNode:Node<T> = this.head;
            let str:string = "";
            let currentPostion:number = 1;
            let prevElement:T;
            let nextElement:T;
            while(currentNode){
                prevElement = currentNode.prev ? currentNode.prev.element : null;
                nextElement = currentNode.next ? currentNode.next.element : null;
                str += `[prev:${prevElement},element:${currentNode.element},next:${nextElement}]  `;
                currentNode = currentNode.next;
                currentPostion++;
            }
            console.log(str + "
    ");
            return str;
        }
    }

    //测试

    let list:DoubleList<string> = new DoubleList<string>();
    list.append("寻秦记");
    list.append("大唐双龙传");
    list.append("四大名捕");
    list.append("笑傲江湖");
    list.append("圆月弯刀");
    list.append("布衣神相");    
    list.print();
    list.removeAt(1);
    list.print();
    list.removeAt(5);
    list.print();

  • 相关阅读:
    对Spring <context:annotation-config/>的理解
    Javascript this指针
    go 打造世界最快的go模板引擎gorazor 2.0
    swagger 部署(Mac )
    Ab测试
    Nginx tcp限制并发、IP、记日志
    Nginx proxy_protocol协议与realip模块
    数据结构之回溯
    数据结构之分治
    数据结构之二分查找
  • 原文地址:https://www.cnblogs.com/kootimloe/p/14199205.html
Copyright © 2011-2022 走看看