链表

链表数据结构

大多数语言中数组的大小是固定的,从数组的起点或中间插入或移除项的成本很高,因为需要移动元素。链表存储有序的元素集合,但不同于数组,链表中的元素在内存中并不是连续放置的。每个元素由一个存储元素本身的节点和指向下一个元素的引用(也称为指针或链接)组成。链表添加或移除元素不需要移动其他元素,然而链表需要使用指针。数组可以访问任意位置的元素,要访问链表元素需要从起点(表头)开始迭代列表直到找到所需的元素。

创建链表

  1. function LinkedList() {
  2. //要加入列表的项
  3. let Node = function(element) {
  4. this.element = element;
  5. this.next = null;
  6. };
  7. let length = 0;
  8. let head = null;
  9. this.append = function(element){};
  10. this.insert = function(position, element) {};
  11. this.removeAt = function(position) {};
  12. this.remove = function(element) {};
  13. this.indexOf = function(element) {};
  14. this.isEmpty = function(){};
  15. this.size = function(){};
  16. this.getHead = function(){};
  17. this.toString = function(){};
  18. this.print = function(){};
  19. }

向链表尾部追加元素

列表为空,添加的是第一个元素,或者列表不为空,向其追加元素。

  1. this.append = function(element){
  2. let node = new Node(element), current;
  3. if(head === null) {
  4. head = node;
  5. } else {
  6. current = head;
  7. //循环列表,直到找到最后一项
  8. while(current.next) {
  9. current = current.next;
  10. }
  11. //找到最后一项,将其next设为node
  12. current.next = node;
  13. }
  14. length++; //更新链表长度
  15. };

从链表中移除元素

移除第一个元素或移除第一个以外的任一元素。我们要实现两种remove方法:第一种是从特定位置移除一个元素,第二种是根据元素的值移除元素。

  1. this.removeAt = function(position) {
  2. //检查越界值
  3. if(position > -1 && position <length) {
  4. let current = head, previous, index = 0;
  5. //移除第一项
  6. if(position === 0) {
  7. head = current.next;
  8. } else {
  9. while(index++ < position) {
  10. previous = current;
  11. current = current.next;
  12. }
  13. //将previous于current的下一项连接起来:跳过current,从而移除他
  14. previous.next = current.next;
  15. }
  16. length--;
  17. return current.element;
  18. } else {
  19. return null;
  20. }
  21. };

在任意位置插入元素

  1. this.insert = function(position, element) {
  2. //检查越界值
  3. if(position >= 0 && position <= length){
  4. let node = new Node(element),
  5. current = head, previous, index = 0;
  6. if(position === 0) {
  7. node.next = current;
  8. head = node;
  9. } else {
  10. while(index++ < position) {
  11. previous = current;
  12. current = current.next;
  13. }
  14. node.next = current;
  15. previous.next = node;
  16. }
  17. length++;
  18. return true;
  19. } else{
  20. return false;
  21. }
  22. };

实现其他方法

  1. //toString()
  2. this.toString = function(){
  3. let current = head, string = '';
  4. while(current) {
  5. string += current.element + (current.next ? 'n' : '');
  6. current = current.next;
  7. }
  8. return string;
  9. };
  10. //indexOf()
  11. this.indexOf = function(element) {
  12. let current = head, index = -1;
  13. while(current) {
  14. if(element === current.element) {
  15. return index;
  16. }
  17. index++;
  18. current = current.next;
  19. }
  20. return -1;
  21. };
  22. //remove()
  23. this.remove = function(element) {
  24. let index = this.indexOf(element);
  25. return this.removeAt(index)
  26. };
  27. this.isEmpty = function(){
  28. return length === 0;
  29. };
  30. this.size = function(){
  31. return length;
  32. };
  33. this.getHead = function(){
  34. return head;
  35. };

双向链表

在双向链表中,链接是双向的。先从实现DoublyLinkedList类所需的变动开始:

  1. function DoublyLinkedList() {
  2. let Node = function(element) {
  3. this.element = element;
  4. this.next = null;
  5. this.prev = null;
  6. };
  7. let length = 0;
  8. let head = null;
  9. let tail = null;
  10. //方法
  11. }

在任意位置插入新元素

  1. this.insert = function(position, element) {
  2. //检查越界值
  3. if(position >= 0 && position <= length) {
  4. let node = new Node(element),current = head, previous, index = 0;
  5. if(position === 0) {
  6. if(!head) {
  7. head = node;
  8. tail = node;
  9. } else {
  10. node.next = current;
  11. current.prev = node;
  12. head = node;
  13. }
  14. } else if(position === length) {
  15. current = tail;
  16. current.next = node;
  17. node.prev = current;
  18. tail = node;
  19. } else {
  20. while(index++ < position) {
  21. previous = current;
  22. current = current.next;
  23. }
  24. node.next = current;
  25. previous.next = node;
  26. current.prev = node;
  27. node.prev = previous;
  28. }
  29. length++;
  30. return true;
  31. } else {
  32. return false;
  33. }
  34. };

从任意位置移除元素

  1. this.removeAt = function(position){
  2. //检查越界值
  3. if(position > -1 && position < length) {
  4. let current = head, previous, index = 0;
  5. //移除第一项
  6. if(position === 0) {
  7. head = current.next;
  8. //如果只有一项,更新tail
  9. if(length === 1){
  10. tail = null;
  11. } else {
  12. head.prev = null;
  13. }
  14. } else if (position === length - 1) {
  15. current = tail;
  16. tail = current.prev;
  17. tail.next = null;
  18. } else {
  19. while(index++ < position) {
  20. previous = current;
  21. current = current.next;
  22. }
  23. previous.next = current.next;
  24. current.next.prev = previous;
  25. }
  26. length--;
  27. return current.element;
  28. } else {
  29. return null;
  30. }
  31. };