JS的class可以通过extends关键字实现类似其他语言的继承效果,比起使用一个extends关键字,在es5中实现继承要复杂一些,可以通过修改原型链的方法实现继承,让一个原型对象等于另一个类型的实例等等,虽然也能够实现,但是不够直观。

constructor()方法中的super()表示调用父类的构造函数,在这里就是调用SIngleList类里面的构造函数。

接下来就可以使用SingleList类中已经实现的函数了,但是由于单向循环链表的某些操作还是不同于单链表的,所以对SingleList类中的一些方法,需要在CirSingleList类中重写。

//继承单链表的属性和方法,有一些方法需要重写

class CirListNode extends ListNode {
constructor() {
super()
}
// 在单循环链表中寻找最后一个节点
/** 使用count进行计数,如果与当前链表的长度相同就返回子节点,这样就可以避免陷入无限循环*/
findLast(): NodeItem {
let count = 0;
let currNode = this.head;
while (currNode.next) {
currNode = currNode.next;
count++;
if (count === this.size) {
return currNode;
}
}
return this.head;
} // 在单循环链表中寻找数据
/** 如果对应元素不存在会导致无限循环,
所以需要重写搜索函数,如果当前节点等于最后一个子节点就结束循环返回null*/
find(item: any): NodeItem {
let lastNode = this.findLast();
let currNode = this.head;
while (currNode.data != item) {
if (currNode == lastNode) {
currNode = null;
break;
}
currNode = currNode.next;
}
return currNode;
} // 在数据为item的节点后面插入数据为element元素的节点
/**
* 1. 插入的是头节点位置,如果当前链表为空,则将新节点插入到head节点后面,并指向自己,形成循环
* 2,插入的是头节点位置,当前链表不为空,则将新节点指向头节点的下一个节点,然后再将头节点指向新节点,再将尾节点指向新节点,形成一个新的循环
* 3, 插入的是中间位置,就正常插入即可
*/
insert(item: any, element: any): void {
let newNode = new NodeItem(element);
let itemNode = this.find(item);
let lastNode = this.findLast();
// 插入的位置处于头结点之后,第一个节点之前
if (item === 'head') {
if (this.size === 0) {
this.head.next = newNode;
newNode.next = newNode;
} else {
newNode.next = this.head.next;
this.head.next = newNode;
lastNode.next = newNode;
}
this.size++;
return;
}
// 处于链表中后位置时
newNode.next = itemNode.next;
itemNode.next = newNode;
this.size++;
} /**
* 1. 当前删除的节点是第一个节点时,如果此时单向循环链表只有一个节点,直接将此单向链表置空即可
* 2. 当前删除的节点是第一个节点时, 且此时单向循环链表不仅只有一个节点时,此时将头节点的next指针指向要删除节点的下一个节点,并将最后一个节点指向要删除节点的下一个节点
* 3. 除了前面的两种情况之外,只要将删除节点的前一个节点next指针指向要删除节点的后一个系欸但即可
*/
remove(item: any): void {
let lastNode = this.findLast();
let itemNode = this.find(item);
let preCurNode = this.head;
while (preCurNode.next !== itemNode) {
preCurNode = preCurNode.next;
}
if (itemNode === this.head.next) {
if (this.size === 1) {
this.head.next = null;
} else {
this.head.next = itemNode.next;
lastNode.next = itemNode.next;
}
} else { preCurNode.next = itemNode.next;
}
this.size--;
} /**
* 根据count计数来输出链表内容,防止陷入无限循环
*/
display(): void {
let count = 0;
let currNode = this.head;
let str = '';
while (count !== this.size) {
currNode = currNode.next;
str += currNode.data + '=>';
count++;
}
console.log(str)
} /**
* 在尾部插入数据
* 用写好的findLast()方法,找到最后一个节点,然后将最后一个节点next指针指向新的节点,再将新的节点指向此链表的第一个节点即可。
*/
append(element: any): void {
let lastNode = this.findLast();
let newNode = new NodeItem(element);
lastNode.next = newNode;
newNode.next = this.head.next;
this.size++;
}
} // n个人围成一圈,杀死第m个人,直到剩下s个人为止
// 输出存活的人的序号
let myList = new CirListNode(); function killPerson(n: any, m: any, s: any) {
for (let i = 1; i <= n; i++) {
myList.append(i);
} let currNode = undefined;
let toKill = null; while(myList.size>s) {
toKill = myList.advance(m, currNode); // 从currNode开始,前进m个节点
currNode = toKill; // 保存要删除的节点作为下一次循环的参数
myList.remove(toKill.data); // 删除第m个节点
}
myList.display();
} killPerson(41, 3, 2); // head->16->31
// killPerson(5, 4, 1); // head->1

最新文章

  1. 虚拟树Demos\Minimal 简单的例子
  2. php : 基础(5)
  3. DFTX 笔试
  4. .NET微信公众号开发-5.0微信支付
  5. 使用StringBuilder更高效的处理字符串
  6. windows installer 出错问题解决
  7. 【和我一起学python吧】python入门语法总结
  8. CSU 1659: Graph Center(SPFA)
  9. TCP/IP小记
  10. JavaScript--AJAX页面传值
  11. 优先队列运用 TOJ 4123 Job Scheduling
  12. Effective java-对象的创建和销毁
  13. vue 脚手架关于路由的一点理解
  14. django的CBV设计模式
  15. rest_famework 增删改查初第四阶段(最高级,此阶段是优化第三阶段的代码)的使用
  16. javaScript之变量与数据类型
  17. C#基础(201)--常量枚举
  18. sql 重复数据查询
  19. 对TCP协议握手的理解(转)
  20. PAT甲级1060 Are They Equal【模拟】

热门文章

  1. java代码常用知识点
  2. Eureka和ZooKeeper都可以提供服务注册与发现的功能,请说说两个的区别?
  3. 请说说你对Hibernat的理解?JDBC和Hibernate各有什么优势和劣势?
  4. Xml 映射文件中,除了常见的 select|insert|updae|delete 标签之外,还有哪些标签?
  5. ThreadLocal是什么?使用场景有哪些?
  6. MySQL安装速成指南(ZIP)
  7. 学习Cobbler(二)
  8. 学习GlusterFS(九)
  9. 单例模式 | C++ | Singleton模式
  10. d面试题汇总