• 动画演示排序算法


    刚开始的思路是用callback返回每一次交换时的元素下标,然后改变left,和top来实现动画演示效果。但是在for循环中setTimeout是不会阻塞代码的执行的,所以得到的是遍历完了的结果。最后,用缓存每一次交换的两个元素对应的dom的下标的方式保存交换的顺序,再用setTimeout显示出来。为了保存数组对应的dom,用

    {                                                   {

      data: ,index:,   的方式,而用       first:,second:,   来存放每次交换的两个元素对应的dom的下标。

    }                                                    }

    希望实现堆排序的完全二叉树展示,未成功,待完成。。。

    <!doctype html>
    <html>
    <head>
    	<style>
    		.bubble {
    			 50px;
    			height: 50px;
    			border: 1px solid #fff;
    			border-radius: 50%;
    			position: absolute;
    			transition: all 0.5s linear;
    			text-align: center;
    			line-height: 50px;
    		}
    		.shadow {
    			background: radial-gradient(circle at 50% 50%, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.3) 40%, rgba(0, 0, 0, 0.4) 10%);
    			-webkit-transform: rotateX(90deg) translateZ(-150px);
    			-moz-transform: rotateX(90deg) translateZ(-150px);
    			-ms-transform: rotateX(90deg) translateZ(-150px);
    			-o-transform: rotateX(90deg) translateZ(-150px);
    			transform: rotateX(90deg) translateZ(-150px);
    			z-index: -1;
    		}
    		.stage {
    			position: relative;
    		}
    		.button-list{
    			position: absolute;
    			top: 100px;
    		}
    	</style>
    </head>
    
    <body>
    	<div class = "stage">
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    		<div class = "bubble">
    			<div class = "shadow"></div>
    		</div>
    	</div>	
    	<div class = "button-list">
    		<button id = "bubbleStart" class = "button">冒泡排序</button>
    		<button id = "insertStart" class = "button">直接插入排序</button>
    		<button id = "shellStart" class = "button">希尔排序</button>
    		<button id = "selectStart" class = "button">选择排序</button>
    		<button id = "heapStart" class = "button">堆排序</button>
    		<button id = "quickStart" class = "button">快速排序</button>
    		<button id = "reset" class = "button">重置</button>
    	</div>
    	<script>
    	    /******************排序算法*******************************/
    		/**
    			生成record
    			@param arr 待排序数组
    		*/
    		function createRecord(arr){
    			let record = [], len = arr.length;
    			for(let i=0; i< len; i++){
    				record[i] = {
    					"data" : arr[i],
    					"index" : i,
    				};
    			}
    			return record;
    		}
    		/**
    			冒泡排序
    			@param arr 待排序数组
    			@return states
    		*/
    		const bubbleSort = function(arr){
    			let exchange = arr.length;
    			let states = [], count=0, record=createRecord(arr);
    			exchange--;
    			while(exchange != 0){
    				bound = exchange; exchange = 0;
    				for(let j=0; j<bound; j++){
    					if(record[j].data > record[j+1].data){
    						let temp = record[j];
    						record[j] = record[j+1];
    						record[j+1] = temp;
    						exchange = j; 
    						//记录原来位置,用来操作dom
    						states[count] = {"first":record[j].index,"second":record[j+1].index,}; 
    						count++;
    					}
    				}
    			}
    			return states;
    		}  
    		/**
    			插入排序
    			@param arr 待排序数组
    			@return states
    		*/
    		function insertSort(arr){
    			let states = [], count = 0, record = createRecord(arr);
    			for(let i = 1,len=record.length; i<len; i++){
    				let temp = record[i]; //保存待插入的数
    				let j = 0;
    				//在有序区中的移动,如果temp较小,就往前移动 
    				for(j=i-1; record[j]!=undefined && temp.data<record[j].data; j--){
    					record[j+1] = record[j] //有序区后移,给temp留插入的空间 
    					//是temp和前面的交换,不能是记录j+1的,因为下一趟J+1就变成之前后移的元素了
    					states[count] = {"first":record[j].index,"second":temp.index,}; 
    					count++;
    				}	
    				record[j+1] = temp; //插入temp  
    			}
    			return states;
    		}
    		/**
    			希尔排序
    			@param arr
    		*/
    		function shellSort(arr){
    			let states = [], count = 0, record = createRecord(arr); 
    			console.log(record);
    			//选择d为len/2
    			let len = record.length-1; //最后的下标
    			//增量缩小 直到小于1跳出
    			for(let d = record.length/2; d>=1; d=parseInt(d/2)){
    				//划分组数的循环 组数为d
    				for(let i=0; i<d; i++){
    					//每一个组都是[i+1,len-d+1] --> 对每一个组直接排序
    					for(let j=i+1; j<=(len-d+1); j++){
    						let temp = record[j];
    						let k = 0;
    						for(k = j-1; record[k] != undefined && temp.data < record[k].data; k--){
    							console.log(1);
    							record[k+1] = record[k];
    							states[count] = {"first":record[k].index,"second":temp.index,};
    							count++;
    						}
    						record[k+1]=temp;
    					}
    				}
    			}
    			return states;
    		}
    		/**
    			选择排序
    			@param arr
    		*/
    		function selectSort(arr){
    			let states = [], count = 0, record = createRecord(arr); 
    			for(let i=0,len=record.length; i<len; i++){
    				index = i;
    				for(let j=i+1; j<len; j++){
    					if(record[j].data<record[index].data)
    						index = j;
    				}
    				//等于就不用交换
    				if(index != i){
    					let temp = record[i];
    					record[i] = record[index];
    					record[index] = temp;
    					states[count] = {"first":record[i].index,"second":record[index].index,}; 
    					count++;
    				}
    			}
    			return states;
    		}
    		/**
    			堆排序
    			@param arr
    		*/
    		function heapSort(arr){
    			let states = [], count = 0, record = createRecord(arr); 
    			//筛选法调整堆的算法
    			/**
    				从顶向下调整子树
    				@param i 需要调整的子树的根结点
    				@param m 子结点的叶子 : 也是无序区的最后一个
    			*/
    			function sift(i,m){
    				console.log(record);
    				let left = 2*i+1; //指向左孩子
    				let right = left + 1; //指向右孩子
    				let maxChild = left;
    				
    				if(left > m) return; //如果左结点越界
    				//如果右孩子不越界
    				if(right <= m && record[left].data<record[right].data){ 
    					maxChild = right;
    				}
    				//如果根结点大于左右孩子
    				if(record[i].data<record[maxChild].data){
    					let temp = record[i];
    					record[i] = record[maxChild];
    					record[maxChild] = temp;
    					states[count] = {"first":record[i].index,"second":temp.index,};
    					count++;					
    					sift(maxChild,m); //递归遍历子树
    				}	
    			}
    			//排序算法
    			function sort(){
    				let len = arr.length - 1;
    				let beginIndex = (len-1) / 2; 
    				//初始建堆
    				for(let i = beginIndex; i>=0; i--){
    					sift(i,len);
    				}
    				
    				//不断移走堆顶和重复建堆
    				for(let i=len; i>0; i--){
    					let temp = record[0];
    					record[0] = record[i];
    					record[i] = temp;
    					states[count] = {"first":record[0].index,"second":temp.index,}; 
    					count++;
    					sift(0,i-1);
    				}
    			}
    			sort();
    			
    			return states;
    		}
    		/**
    			快速排序
    			@param arr
    		*/
    		function quickSort(arr){
    			let states = [], count = 0, record = createRecord(arr); 
    			//一次划分	
    			function partition(first,end){
    				let i = first, j = end;
    				while(i < j){
    					while(i<j && record[i].data<=record[j].data) j--; //右侧扫描
    					if(i<j){
    						let temp = record[i];
    						record[i] = record[j];
    						record[j] = temp;
    						states[count] = {"first":record[i].index,"second":record[j].index,}; 
    						i++;
    						count++;
    					}
    					while(i<j && record[i].data<=record[j].data) i++; //左侧扫描
    					if(i<j){
    						let temp = record[i];
    						record[i] = record[j];
    						record[j] = temp;
    						states[count] = {"first":record[i].index,"second":record[j].index,}; 
    						j--;
    						count++;
    					}
    				}
    				return i;
    			}
    			
    			function sort(first,end){
    				if(first<end){
    					let pivot = partition(first,end);
    					sort(first,pivot-1);
    					sort(pivot+1,end);
    				}
    			}
    			sort(0,record.length-1);
    			
    			return states;
    		}
    		/***************************************************************/
    		/**
    			设置演示用的dom的样式
    			@param doms dom对象
    			@param arr 待排序数组
    		*/
    		function domStyle(doms,arr){
    			const MAX = 255;
    			const MIN = 0;
    			for(let i = 0,len = doms.length; i < len; i++){
    				let r = Math.floor(Math.random()*(MAX-MIN+1) + MIN); 
    				let g = Math.floor(Math.random()*(MAX-MIN+1) + MIN); 
    				let b = Math.floor(Math.random()*(MAX-MIN+1) + MIN); 
    				doms[i].innerText = arr[i]; 
    				let startColor = "rgba(" + 255 + "," + 255 + "," + 255 + "," + 0 + ")";
    				let endColor = "rgba(" + r + "," + g + "," + b + "," + 1 + ")";
    				doms[i].style.background = "radial-gradient(circle at 50% 50%,"+startColor+","+ endColor+")";
    				reset(doms);
    			}
    		}
    		/**
    			重置
    			@param doms
    		*/
    		function reset(doms){
    			let w = doms[0].offsetWidth;
    			for(let i=0,len=doms.length; i<len; i++){
    				doms[i].style.left = w * i + "px";
    			}
    		}
    		/**
    			生成完全二叉树样式
    			@param doms 球体数组
    		*/
    		function createTree(doms){
    		
    		}
    		/**
    			演示
    			@param doms 演示用的dom对象
    			@param arr states数组对象
    			@param btn 对应按钮
    		*/
    		function domOpera(doms,arr,btn){
    			let i = 0,len = arr.length;
    			btn.setAttribute("disabled","disabled");
    			console.log(arr);
    			/*
    			for(let i = 0; i<arr.length; i++){
    				timeout(i);
    			}*/
    			function timeout(){
    				if(timer){
    					clearTimeout(timer);
    				}
    				timer = setTimeout(function(){
    					let tempLeft = doms[arr[i].first].style.left;
    					//doms[arr[i].first].style.transform = "translateX(" + doms[arr[i].second].style.left + ")";
    					doms[arr[i].first].style.left = doms[arr[i].second].style.left;
    					doms[arr[i].second].style.left = tempLeft;
    					i++;
    					if(i<len) timeout();
    					else{
    						timer = setTimeout(function(){
    							reset(doms);
    							btn.removeAttribute("disabled");
    						},2000);
    					}
    				},1000);
    			}
    			timeout();
    		}
    		let timer = null;
    		window.onload = function(){
    			let arr = [50,13,12,56,87,58,45,90]; //待排序数组
    			let doms = document.getElementsByClassName("bubble"); //doms对象
    			let btns = document.getElementsByClassName("button"); //button
    			domStyle(doms,arr); //显示球体样式
    			//绑定事件
    			btns[0].onclick = function(){
    				domOpera(doms,bubbleSort(arr),this); 
    			}
    			btns[1].onclick = function(){
    				domOpera(doms,insertSort(arr),this);
    			}
    			btns[2].onclick = function(){
    				domOpera(doms,shellSort(arr),this);
    			}
    			btns[3].onclick = function(){
    				domOpera(doms,selectSort(arr),this);
    			}
    			btns[4].onclick = function(){
    				createTree(doms);//生成完成二叉树样式
    				domOpera(doms,heapSort(arr),this);
    			}
    			btns[5].onclick = function(){
    				domOpera(doms,quickSort(arr),this);
    			}
    			//重置
    			btns[6].onclick = function(){
    				clearTimeout(timer);
    				for(let i=0; i<9; i++){
    					if(btns[i].hasAttribute("disabled")){
    						btns[i].removeAttribute("disabled");
    						break;
    					}
    				}
    				reset(doms);
    			}
    		}
    	</script>
    </body>
    
    </html>
    

      

    				

      效果:

         

  • 相关阅读:
    北京Uber优步司机奖励政策(2月26日)
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月26日)
    北京最牛的医院 最牛的科室排名出炉
    滴滴快车奖励政策,高峰奖励,翻倍奖励,按成交率,指派单数分级(2月25日)
    北京Uber优步司机奖励政策(2月25日)
    成都Uber优步司机奖励政策(2月25日)
    优步(UBER)发布2016年春节出境游出行报告
    cpp
    cpp
    Linux
  • 原文地址:https://www.cnblogs.com/githubMYL/p/8909700.html
Copyright © 2020-2023  润新知