数据结构:冒泡排序和选择排序的实现(java)

1.冒泡排序

(1)顺序结构实现(数组)

编程时的思路:

1.比较第一个和第二个元素,若第一个元素大于第二个元素,两个元素交换。
2.比较第二个和第三个元素,若第二个元素大于第三个元素,两个元素交换。

3.比较倒数第二个和最后一个元素,若倒数第二个元素大于最后一个元素,两个元素交换。

以上就可以写成一个循环,结果就是把数组最大的那个元素放到了最后的位置。

4.然后就要除去放了最大元素的位置,进行下一次循环,找出剩下的元素中最大的元素。
5.多次循环,不断找出最大的元素,当剩下的元素只有一个时,程序结束。

以上就可以写成一个嵌套循环,每一次内循环结束,外循环都让内循环的末尾位置(挡板)往前移动一个位置。

代码:

	public static void bubbleSort(int[] arr) {
		
		int i=arr.length;
		while(i>0) {   //外循环实现一个挡板,每一次内循环结束,i-1。
			
			for(int j=0;j<i-1;j++) {  //随着i不断减1,这个循环会一次次地找到剩下元素的最大元素  
				int temp;    
				if(arr[j]>arr[j+1]) {
					temp=arr[j];
					arr[j]=arr[j+1];
					arr[j+1]=temp;
				}
			}
			i--;
		}		
	}

(2)链式结构实现(链表)

编程时的思路:

大体上和顺序结构的差不多,都是用嵌套循环。

关键是实现末尾位置前移(挡板前移),这个需要设置多一个节点。

首先设置p为head节点,开始遍历链表,当完成一次循环之后,此时p就是倒数第二个位置的节点,要向让挡板前移,开始第二轮循环,就要设置一个节点q,让q得到p此时的位置。实现挡板的前移。

代码:

public class TestDemo {

	public static void main(String[] args) {
		
		int[] arr={23,85,67,134,7,99};
		
		linklist list = new linklist();
		
		for(int i=0;i<arr.length;i++) {
			list.bulidlinklist(arr[i]);
		}
		
		list.sort();
		
		list.printlist();	
	}
}

//链表的节点类
class Node2{
	int data;
	Node2 next;
	
	Node2(int data){
		this.data=data;
		this.next=null;
	}
}

//链表类
class linklist{
	
	Node2 head;
	
	void bulidlinklist(int data){
		Node2 n = new Node2(data);
		if(head==null) {
			head=n;
		}else {
			n.next=head;
			head=n;
		}
	}
	
	void printlist() {
		Node2 p=head;
		while(p!=null) {
			System.out.print(p.data+" " );
			p=p.next;
		}
	}
	
	//冒泡排序算法
	void sort() {
		Node2 p=head;  //p是用于遍历链表的
		Node2 q=null;  //q是用于实现挡板前移的
		
		while(p!=q) {  //外循环,q在不断向前移动中,当p等于q,说明链表只有一个节点了,排序完成结束
			while(p.next!=q) {
				int temp;
				if(p.data>p.next.data) {
					temp=p.data;
					p.data=p.next.data;
					p.next.data=temp;
				}
				p=p.next;
			}
			q=p;   //在p不断等于p.next中,当完成了一次循环,p就是挡板前的那部分链表的倒数第二个节点,此时让q=p,刚好实现挡板前移的效果
			
			p=head;  //重置p,开始新的一轮循环遍历
		}
	}	
}

2.选择排序

(1)顺序结构实现(数组)

编程时的思路:
1.定义一个最小值变量smallest=数组的一个元素,让其分别和数组的每一个元素对比大小,如果smallest大于这个元素,则让更新smallest为这个元素,同时用flag记录这个元素在数组中的索引。

以上可以用一个循环遍历找出未实现排序的数组部分的最小值。

2.找出这些元素的最小值后,让该最小值的元素更改为:该未实现排序的数组部分的第一个元素,接着让该未实现排序的数组部分的第一个元素更改为smallest,实现数据的交换。
3.此时已经排好了一个元素,让挡板右移,对未实现排序的数组部分继续实行上述操作。

以上就可以写成一个嵌套循环,直到未实现排序的数组部分只剩下一个元素,程序结束。

代码:

	public static void sellctionSort(int[] arr) {
		
		int n=0;

		while(n<arr.length-1 ) {   //实现挡板右移,区分开未实现排序的数组部分和已经实现排序的数组部分
			
			int smallest=arr[n];    //让smallest暂时等于未实现排序的数组部分的首元素
			int flag=0;
			
			for(int i=n;i<arr.length;i++) {
				
				if(smallest>arr[i]) {
					smallest=arr[i];
					flag=i;     //记录未实现排序的数组部分的最小元素的索引,便于交换数据
				}
			}
			
			if(flag!=0) {   //当flag是0,说明smallest暂时等于未实现排序的数组部分的首元素,刚刚好就是未实现排序的数组部分的首元素的最小元素,不用交换。
				arr[flag]=arr[n];
				arr[n]=smallest;
			}
			
			n++;
		}	
	}

(2)链式结构实现(链表)

编程思路:
跟顺序结果没有什么差别,主要是交换节点过于麻烦,直接交换数据就可以了。

交换数据时,不能用flag记录索引,要再循环一次,找出最小值元素用于交换,以为没有链表没有索引可以直接找到

代码:

public class TestLinklist {

	public static void main(String[] args) {
		int[] arr= {12,53,13,65,24};
		Singlelist list = new Singlelist(arr);
		
		list.printlist();
		System.out.println();
		
		list.selectionsort();
		list.printlist();
		
	}

}

class Node1{
	int data;
	Node1 next;
	
	Node1(int data){
		this.data=data;
		this.next =null;
	}
	
}


class Singlelist{
	Node1 head;

	Singlelist(int data[]){
		for(int i=0;i<data.length;i++) {
			if(head==null) {
				head=new Node1(data[i]);
				
			}else {
				
				Node1 p = new Node1(data[i]);
				p.next=head;
				head=p;
			}
		}
	}
	
	
	void printlist() {
		Node1 p =this.head;
		
		while(p!=null) {
			System.out.print(p.data+" ");
			p=p.next;
		}
	}
	
	void selectionsort() {
		
//		Node1 p = head;
//		Node1 smallest = p;
//		//此时head,p,smallest三个地址是一样的,都是head,名称不同而已

		Node1 r=head;
		while(r.next!=null) {  //实现挡板右移
					
			Node1 p =r;
			int smallest= p.data;
			
			while(p.next!=null) {    //找出找出未实现排序的数组部分的最小值
				
				if(smallest>p.next.data) {
					smallest = p.next.data;
				}
				p=p.next;
			}
			
			Node1 q = r;
			while(q!=null) {      //再循环一次,找出最小值元素用于交换,以为没有链表没有索引可以接着找到
				if(q.data==smallest) {
					q.data=r.data;
					break;
				}
				q=q.next;
			}
			r.data=smallest;
			
			r=r.next;
		}	
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值