数据结构--链表

链表分类: 
1、单向链表
2、双向链表
3、环形链表

基本概念:
链表实际上是线性表的链式存储结构,与数组不同的是,它是用一组任意的存储单元来存储线性表中的数据,存储单元不一定是连续的。
每个节点都包含两个部分,第一部分称为链表的数据区域,用于存储元素本身的数据信息,这里用data表示,
第二部分是一个结构体指针,称为链表的指针域,用于存储其直接后继的节点信息,这里用next表示,
next的值实际上就是下一个节点的地址。当前节点为末节点时,next的值设为空指针。

链表的基本结构:

链表应用场景:
链表常用于在程序中临时存储一组不定长的线性数据。
1,数据是逐渐增加的
2,数据是不定长的,在存储第一个数据之前难以确定一个将来一共需要存储多少数据的上限,或者虽可确定上限,但这个上限又比通常大部分情况下数据可能达到的长度要大得多,因而一次性按照上限把空间分配好是不划算的。

链表的特点:

优点:非常方便地实现节点的插入和删除操作,而数组需要移动非常多的步骤。
缺点:链表只能顺序访问,无法得到任意一个位置的元素,链表这种存储方式最大缺点就是容易出现断链。一旦链表中某个节点的指针域数据丢失,那么意味着将无法找到下一个节点,该节点后面的数据将全部丢失。

使用js创建链表:

增加append(val),删除removeAt(position),插入insert(position,val),输出节点toString(),以及索引indexOf(val)。参考链接

function LinkedList() {
    var Node = function (val) {       //新元素构造
        this.val = val;
        this.next = null;
    };
    var length = 0;
    var head = null;
   
    this.append = function (val) {
        var node = new Node(val);       //构造新的元素节点
        var current;
        if (head === null) {        //头节点为空时  当前结点作为头节点
            head = node;
        } else {
            current = head;              
            while (current.next) {     //遍历,直到节点的next为null时停止循环,当前节点为尾节点
                current = current.next;
            }
            current.next = node;      //将尾节点指向新的元素,新元素作为尾节点
        }           
        length++;              //更新链表长度
    };
    this.removeAt = function (position) {
        if (position > -1 && position < length) {
            var current = head;
            var index = 0;
            var previous;
            if (position == 0) {
                head = current.next;
            } else {
                while (index++ < position) {
                    previous = current;
                    current = current.next;
                }
                previous.next = current.next;
            }
            length--;
            return current.val;
        } else {
            return null;
        }
    };
    this.insert = function (position, val) {
        if (position > -1 && position <= length) {   //校验边界
            var node = new Node(val);        
            current = head;
            var index = 0;
            var previous;
            if (position == 0) {       //作为头节点,将新节点的next指向原有的头节点。
                node.next = current;
                head = node;         //新节点赋值给头节点
            } else {
                while (index++ < position) {
                    previous = current;
                    current = current.next;
                }               //遍历结束得到当前position所在的current节点,和上一个节点
                previous.next = node;    //上一个节点的next指向新节点  新节点指向当前结点,可以参照上图来看
                node.next = current;
            }
            length++;
            return true;
        } else {
            return false;
        }
    };
    this.toString = function () {
        var string = head.val;
        var current = head.next;        
        while (current) {
            string += ',' + current.val;
            current = current.next;
        }
        return string;
    };
    this.indexOf = function (val) {
        var current = head;
        var index = -1;
        while (current) {
            if (val === current.val) { //从头节点开始遍历
                return index;
            }
            index++;
            current = current.next;
        }
        return -1;
    };
    this.getLength = function () {
        return length;
    }
    this.getHead = function () {
        return head;
    }
}
 
// 创建链表
var li = new LinkedList();
li.append(1);
li.append(2);
li.append(4);
li.append(4);
li.append(5);
li.insert(2,3);
li.insert(2,3);
console.log(li.toString())  // 1,2,3,3,4,4,5
console.log(li.getHead())   // 1->2->3->3->4->4->5

 

posted @ 2020-10-26 19:20  梁涛999  阅读(718)  评论(0编辑  收藏  举报