// 封装一个栈functionStack(){this.items =[]// 实现栈的基本操作// 1.将元素压入栈Stack.prototype.push=function(ele){this.items.push(ele)}// 2.将栈顶移除并返回Stack.prototype.pop=function(){returnthis.items.pop()}// 3.查看一下栈顶元素Stack.prototype.peek=function(){returnthis.items[this.items.length-1]}// 4.判断栈是否为空Stack.prototype.isEmpty=function(){returnthis.items.length ==0}// 5.获取栈中元素的个数Stack.prototype.size=function(){returnthis.items.length
}// 6.toString方法 将栈中元素获取为字符串Stack.prototype.toString=function(){var total =""for(var i=0;i<this.items.length;i++){
total +=this.items[i]+" "}return total
}}// 构建一个栈var p =newStack()// p.push(12)// p.push(13)// p.push(14)// p.push(12)// p.pop()// b = p.pop()// a = p.peek()// c = p.isEmpty()// d = p.size()// e = p.toString()// console.log(p)// console.log(a)// console.log(b)// console.log(c)// console.log(d)// console.log(e)// 函数十进制转二进制functiondec2bin(ele){// 构建一个栈var stack =newStack// 循环操作while(ele>0){// 往栈里加ele的余数
stack.push(ele%2)
ele = Math.floor(ele /2)}// 将我们的栈余数取出来var eleResult =""while(!stack.isEmpty()){
eleResult += stack.pop()}return eleResult
}
console.log(dec2bin(100))
队列结构
// 封装队列functionQueue(){// 用数组封装this.items =[]// 1.将元素添加到队列中Queue.prototype.enqueue=function(ele){this.items.push(ele)}// 2.将队列中第一个元素删除Queue.prototype.dequeue=function(){returnthis.items.shift()}// 3.检查最前端元素Queue.prototype.front=function(){returnthis.items[0]}// 4.查看队列是否为空Queue.prototype.isEmpty=function(){returnthis.items.length ==0}// 5.查看队列中元素个数Queue.prototype.size=function(){returnthis.items.length
}// 6.toString 方法Queue.prototype.toString=function(){var result =""for(var i =0;i<this.items.length;i++){
result +=this.items[i]+" "// result += this.items[i] }return result
}}var queue =newQueue()// Queue.enqueue("sada")
queue.enqueue("sada")// queue.enqueue("sada")// queue.enqueue("sada")// queue.enqueue("45646")// queue.enqueue("45646")// queue.enqueue("45646")// queue.enqueue("45646")// 用alert 的话可以执行一遍整个函数// 故不用返回tostring方法来获取alert(queue)// console.log(queue)// 面试题 // 击鼓传花functionpassGame(namelist,num){// 创建一个队列var queue =newQueue()// 1.将名字顺序传进去for(var i=0;i<namelist.length;i++){
queue.enqueue(namelist[i])}// 当队列大小为1时停止游戏while(queue.size()>1){// 2.将num之前的元素全部放到最后for(var i =0;i<num -1;i++){
queue.enqueue(queue.dequeue())}// 3.将为nun的去掉
queue.dequeue()}// 将剩下的那个获胜者及角标取出var result = queue.front()// 获取一开始的位置var biao = namelist.indexOf(result)alert("剩下的人时"+result+"他的位置为"+biao)}// passGame(["lige","dasda","dwhi","beijing","guangzhou"],5)
优先级队列封装
// 封装一个优先级队列functionpriorityQueue(){// 内建一个类封装数据functioneleQueue(ele, priority){this.ele = ele
this.priority = priority
}// 构建一个队列this.items =[]// 1.添加一个元素插入方法
priorityQueue.prototype.addQueue=function(ele, priority){// 创建一个eleQueue对象获取数据var queue =neweleQueue(ele, priority)// 判断数组是否为空if(this.items.length ==0){this.items.push(queue)}// 否就执行添加方法else{// 创建一个标志类似于质数检查var istrue =truefor(var i =0; i <this.items.length; i++){if(queue.priority <this.items[i].priority){// 数组的插入在前插入this.items.splice(i,0, queue)
istrue =falsebreak}}if(istrue){this.items.push(queue)}}}// 2.将队列中第一个元素删除
priorityQueue.prototype.dequeue=function(){returnthis.items.shift()}// 3.检查最前端元素
priorityQueue.prototype.front=function(){returnthis.items[0]}// 4.查看队列是否为空
priorityQueue.prototype.isEmpty=function(){returnthis.items.length ==0}// 5.查看队列中元素个数
priorityQueue.prototype.size=function(){returnthis.items.length
}// 6.toString 方法
priorityQueue.prototype.toString=function(){var result =""for(var i =0; i <this.items.length; i++){
result +=this.items[i].ele +"-"+this.items[i].priority +" "// result += this.items[i] }return result
}}var pq =newpriorityQueue()
pq.addQueue(2,100)
pq.addQueue(3,400)
pq.addQueue(5,500)
pq.addQueue(3,20)
pq.addQueue(4,200)alert(pq)
列表结构
单向链表的封装
// 封装单向链表类functionLinkList(){// 封装一个内部类:节点类functionNode(data){this.data = data;this.next =null;}// 属性// 属性head指向链表的第一个节点this.head =null;this.length =0;// 一.实现append方法LinkList.prototype.append=data=>{//1.创建新节点let newNode =newNode(data)//2.添加新节点//情况1:只有一个节点时候if(this.length ==0){this.head = newNode
//情况2:节点数大于1,在链表的最后添加新节点 }else{//让变量current指向第一个节点let current =this.head
//当current.next(下一个节点不为空)不为空时,一直循环,直到current指向最后一个节点while(current.next){
current = current.next
}// 最后节点的next指向新的节点
current.next = newNode
}//3.添加完新结点之后length+1this.length +=1}// 二、实现toString方法LinkList.prototype.toString=()=>{// 1.定义变量let current =this.head
let listString =""// 2.循环获取一个个的节点while(current){
listString += current.data +" "
current = current.next//千万不要忘了拼接完一个节点数据之后,让current指向下一个节点}return listString
}// 3. insert方法LinkList.prototype.insert=function(positon,data){// 对position进行一个合法判断if(positon <0|| positon >this.length ){returnfalse}// 创建新的节点var newNode =newNode(data)// 将节点插入if(positon ==0){// 当position为0时将元素插入最前面
newNode.next =this.head
this.head = newNode
}else{// 创建变量index来定位current到positon处位置var index =0var current =this.head
var previous =nullwhile(index++< positon){// current定位到position处
previous = current
current = current.next
}// 将newCode插入进来
newNode.next = current
previous.next = newNode
}// 最后整体长度 length +1this.length +=1returntrue}// 4. get 方法 获取对应位置元素的数据LinkList.prototype.get=function(position){// 判断position 是否合法if(position <0|| position >=this.length)returnnull// 创建一个标识var index =0var current =this.head
while(index++< position){
current = current.next
}return current.data
}// 5. indexOf 方法 查看对应数据的下标LinkList.prototype.indexOf=function(data){var index =0var current =this.head
while(current){if(current.data == data){return index
}
current = current.next
index +=1}return-1}// 6. updata 方法 可以更新对应位置的数据LinkList.prototype.updata=function(position,data){if(position <0|| position >=this.length)returnfalsevar index =0var current =this.head
while( index < position){
current = current.next
index +=1}
current.data = data
returntrue}// 7. removeAt 方法 将对应位置的元素删除LinkList.prototype.removeAt=function(position){if(position <0|| position >=this.length)returnnullvar index =0var current =this.head
var previous =nullif(position ==0){this.head =this.head.next
}else{while(index++< position){
previous = current
current = current.next
}
previous.next = current.next
}// 设置长度减一this.length -=1return current.data
}// 8.remove 方法 根据元素来定位删除对应的节点LinkList.prototype.remove=function(data){var positon =this.indexOf(data)returnthis.removeAt(positon)}// 9.isEmpty 方法判断链表是否为空LinkList.prototype.isEmpty=function(){returnthis.length ==0}// 10.size 判断链表大小LinkList.prototype.size=function(){returnthis.length
}}//测试代码//1.创建LinkListlet list =newLinkList()//2.插入数据
list.append('aaa')
list.append('aaa')
list.append('bbb')
list.append('bbb')
list.append('ccc')
console.log(list);// list.insert(0,"dsa")// var a= list.get(0)// console.log(list.toString() + a )// list.updata(2,"hwc")// console.log(list.toString()) // // 测试removeAt方法// list.removeAt(0)// console.log(list.toString()) // // 测试remove 方法// list.remove("hwc")// console.log(list.toString()) // alert(list.isEmpty())// alert(list.size())
双向链表的封装
functiondoubleLink(){// 内部类 functionlink(data){this.data = data
this.prev =nullthis.next =null}// 属性 this.length =0this.tail =nullthis.head =null//1. append 方法
doubleLink.prototype.append=function(data){// 引入数据var newNode =newlink(data)if(this.length ==0){this.head = newNode
this.tail = newNode
}else{this.tail.next = newNode
newNode.prev =this.tail
this.tail = newNode
}// 然后总体长度加1this.length +=1}// 2.insert 方法 在指定位置插入节点
doubleLink.prototype.insert=function(position,data){// 判断定位的位置是否合法if(position <0&& position >this.length )returnfalse// 创建变量var index =0var current =this.head
var newNode =newlink(data)if(position ==0){// 1. 第一种为0插入到头的节点 this.head.prev = newNode
newNode.next =this.head
this.head = newNode
}elseif(position ==this.length){// 第二种插入到末尾的节点this.tail.next = newNode
newNode.prev =this.tail
this.tail = newNode
}else{// 第三种插入到中间的节点while(index ++< position){// 让current 定位到要插入的节点位置
current = current.next
}// 定位完成后开始插入
newNode.prev = current.prev
newNode.next = current
current.prev.next = newNode
current.prev = newNode
}// 总体长度加1this.length +=1returntrue}// 将链表转为字符串的方法// 1. backwards 向后遍历 toString方法
doubleLink.prototype.toString=function(){var result =""var current =this.head
while(current){
result += current.data +" "
current = current.next
}return result
}// 2.forwards 方法从后向前遍历
doubleLink.prototype.forwards=function(){var result =""var current =this.tail
while(current){
result += current.data +" "
current = current.prev
}return result
}// 3. get 方法获取对应位置节点的数据
doubleLink.prototype.get=function(position){if(position <0|| position >=this.length){returnnull}// 2分遍历 提升效率if(this.length /2> position){var current =this.head
var index =0while(index++<position){
current = current.next
}}else{var current =this.tail
var index =this.length-1while(index-->position){
current = current.prev
}}return current.data
}// 4.indexOf 方法 返回元素所在节点位置,没找到就返回-1
doubleLink.prototype.indexOf=function(data){var current =this.head
var index =0while(current){if(current.data == data){return index
}
index ++
current = current.next
}return-1}// 5.updata 方法 修改某个位置的元素
doubleLink.prototype.updata=function(position , data){if(position <0||position>=this.length)returnfalsevar current =this.head
var index =0while(index++<position){
current = current.next
}
current.data = data
}// 6. removeAt 方法 移除特定位置的节点
doubleLink.prototype.removeAt=function(position){if(position <0||position>=this.length)returnfalsevar current =this.head
var index =0if(position ==0){this.head =this.head.next
this.head.prev =null}elseif(position ==this.length-1){this.tail =this.tail.prev
this.tail.next =null}else{while(index++< position){
current = current.next
}
current.prev.next = current.next
current.next.prev = current.prev
}this.length --return current.data
}// 7. remove 方法根据元素来删除指定节点
doubleLink.prototype.remove=function(data){returnthis.removeAt(this.indexOf(data))}// 8. isEmpty 方法
doubleLink.prototype.inEmpyt=function(){returnthis.length ==0}// 9. size 方法
doubleLink.prototype.size=function(){returnthis.length
}// 10.getHead获取链表第一个元素
doubleLink.prototype.getHead=function(){returnthis.head.data
}// 11.getTail获取链表最后一个元素
doubleLink.prototype.getTail=function(){returnthis.tail.data
}}// 代码测试var lk =newdoubleLink()
lk.append("aaa")
lk.append("bbb")
lk.append("ccc")
lk.append("ccc")// alert(lk)// alert(lk.forwards())// 测试 insert 方法
lk.insert(0,"abc")
lk.insert(5,"hwc")
lk.insert(2,"ljc")
console.log(lk.toString());// get方法的测试// console.log(lk.get(0));// console.log(lk.get(6));// indexOf 方法的测试// console.log(lk.indexOf("hwc"));// console.log(lk.indexOf("ljc"));// updata 方法的测试// lk.updata(0,"woshinidie")// lk.updata(6,"inidie")// removeAt 方法测试// lk.removeAt(0) // console.log(lk.remove(6));// lk.removeAt(1)// remove 方法的测试// lk.remove("hwc")// lk.remove("ljc")// console.log(lk.toString()); // 其他方法的测试// console.log(lk.inEmpyt());// console.log(lk.size());// console.log(lk.getHead());// console.log(lk.getTail());
反转链表
varreverseList=function(head){if(!head)returnnullvar p = head.next
head.next =null// 让头节点变为尾节点var temp
while(p){
temp = p.next // 让迭代的节点next指向前一个节点
p.next = head
head = p
p = temp
}return head
};// 递归的基线条件:遍历到末节点(node.next === null)// 递归的递归条件:node.next !== null// 当遇到末节点时,返回末节点,前一节点接收末节点,并把末节点的next设置为自身,返回前一节的,继续下去// 考虑特殊情况:undefined和nullvarreverseList=function(head){// 闭包if(head ===undefined|| head ===null)returnnullvar originalHead = head
var reverseHead
varreverse=function(head){if(head.next ===null){
reverseHead = head
return head
}else{var node =reverse(head.next)
node.next = head
if(originalHead === head){
head.next =nullreturn reverseHead
}else{return head
}}}returnreverse(head)};
var len
// 建立最大堆functionbuildMaxHeap(arr){
len = arr.length
// 从非叶子节点开始调整for(let i = Math.floor(len/2); i>=0;i--){heapify(arr,i)}}// 堆调整functionheapify(arr,i){var left =2*i+1var right =2*i+2var largest = i
if(left < len && arr[left]>arr[largest]){
largest = left
}if(right < len && arr[right]>arr[largest]){
largest = right
}if(largest != i){swap(arr,i,largest)heapify(arr,largest)}}functionswap(arr,m,n){var temp = arr[m]
arr[m]= arr[n]
arr[n]= temp
}functionheapSort(arr){// 建立最大堆buildMaxHeap(arr)// 将堆顶元素放到末尾for(let i = arr.length-1;i>0;i--){swap(arr,0,i)
len--// 每次交换完后调整堆heapify(arr,0)}return arr
}let arr =[12,3,2,4,5,2,1,3]
console.log(heapSort(arr));
归并排序
functionmergeSort(arr){if(arr.length<2){return arr
}// 分var middle = Math.floor(arr.length/2)var left = arr.slice(0,middle)var right = arr.slice(middle)returnmerge(mergeSort(left),mergeSort(right))// 治functionmerge(left,right){var result =[]while(left.length && right.length){if(left[0]< right[0]){
result.push(left.shift())}else{
result.push(right.shift())}}while(left.length){
result.push(left.shift())}while(right.length){
result.push(right.shift())}return result
}}
console.log(mergeSort([1,3,5,7,2,4,6,8]));
快速排序
// 快速排序的思想// (1)在数据集之中,选择一个元素作为"基准"(pivot)。// (2)所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边。// (3)对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。varquickSortFind=function(arr){// 递归结束条件if(arr.length<=1){return arr
}// 从中间开时选择基准元素var center = Math.floor(arr.length/2)var pivot = arr.splice(center,1)[0]var left =[]var right =[]// 循环比较出比基准小的加在左数组,大的加到右数组for(var i =0;i<arr.length;i++){if(arr[i]< pivot){
left.push(arr[i])}else{
right.push(arr[i])}}// 最后循环递归出所有子集剩下一个元素时再并成一个数组return[...quickSortFind(left),pivot,...quickSortFind(right)]// quickSortFind(left).concat(pivot,quickSortFind(right))}
console.log(quickSortFind([1,3,5,7,2,4,6,8]));
冒泡排序,希尔,多重排序
functionarrayList(){// 属性this.array =[]// 方法// 添加元素的方法
arrayList.prototype.insert=function(key){this.array.push(key)}// 重写toString方法
arrayList.prototype.toString=function(){returnthis.array.join("-")}// 元素交换方法
arrayList.prototype.swap=function(m,n){var c =this.array[m]this.array[m]=this.array[n]this.array[n]= c
}// 冒泡排序
arrayList.prototype.bubbleSort=function(){
length =this.array.length
for(let j =0;j<length;j++){for(let i =0;i<length-1-j;i++){if(this.array[i]>this.array[i+1]){this.swap(i,i+1)}}}}// 选择排序
arrayList.prototype.selectionSort=function(){
length =this.array.length
// 外层循环从0开始一个一个进行选择for(let i =0;i<length-1;i++){var min = i
// 内层循环 将min 跟列表内min+1的元素一个一个进行对比for(let j = min+1;j<length;j++){if(this.array[min]>this.array[j]){
min = j
}}// 将选择完的元素进行对调this.swap(min,i)}}// 插入排序
arrayList.prototype.insertSort=function(){var length =this.array.length
// 从i位置开始取出for(let i =1;i<length;i++){var temp =this.array[i]var j = i
// 将i位置的元素一次和前面进行比较while(this.array[j-1]> temp && j>0){this.array[j]=this.array[j-1]
j--}// 比较完后j位置的数据放置tempthis.array[j]= temp
}}// 希尔排序
arrayList.prototype.shell=function(){var gap = Math.floor(this.array.length /2)while(gap>=1){for(let i =gap;i<this.array.length;i++){var temp =this.array[i]var j = i
// 逐步向前比较排序while(this.array[j-gap]> temp &&j>=gap-1){this.array[j]=this.array[j-gap]
j -= gap
}this.array[j]= temp
}
gap = Math.floor(gap /2)}}}// 测试const list =newarrayList()
list.insert(213)
list.insert(2)
list.insert(3)
list.insert(1)
list.insert(5)
list.insert(3)
list.insert(333)
list.insert(22)
list.insert(15)
list.insert(33)
list.insert(22)// 冒泡排序
list.bubbleSort()alert(list)// 选择排序// list.selectionSort()// 插入排序// list.insertSort()// 希尔排序// list.shell()alert(list)