写给自己看的单链表(3):冒泡排序和插入排序

!!!Attention:以下操作中的单链表均带有头结点!!!
1.冒泡排序
首先要获取单链表的长度n。
冒泡排序的基本思路是:从某一方向开始,依次两两比较,把小的放左边,大的放右边。由于单链表的单向性,这里的“冒泡”并不是将更小的元素移到更前的位置,而是反过来,将更大的元素移到更后的位置。程序的主体由两个嵌套的循环构成,外部循环要进行n-1次,内部的循环用于进行相邻元素之间的两两比较。经过第一次外部循环后,最大的元素被移至链表的最末;以此类推。
bubblesort

void BubbleSort(Lnode *head)
{
	Lnode *current, *prev, *tmp;
	current = head;
	int n = 0;
	while (current != NULL) { //Find length of the list, length = n
		n++;
		current = current->next;
	}
	for (int i = 0; i < n; i++) { //n-1 cycles
		prev = head; //Every cycle begins from head
		current = head->next;
		for (int j = n - 1- i; j > 0; j--) { //n-1-i comparisons in every cycle
			if (current->next != NULL && current->data > current->next->data) {
				tmp = current->next;
				prev->next = tmp;
				current->next = tmp->next;
				tmp->next = current;
				prev = tmp;
			}
			else {
				prev = current;
				current = current->next;
			}
		}
	}
}

2.插入排序
引自单链表的插入排序

插入排序的基本思想:将一个节点插入到一个有序的序列中。对于链表而言,要依次从待排序的链表中取出一个节点插入到已经排好序的链表中,也就是说,在单链表插入排序的过程中,原链表会截断成两部分,一部分是原链表中已经排好序的节点,另一部分是原链表中未排序的节点,这样就需要在排序的过程中设置一个当前节点,指向原链表未排序部分的第一个节点。

思路:
1.定义三个指针,current记录未排序部分的第一个节点,prev用于遍历已排序部分,tail记录已排序部分的最后一个节点。
2.遍历已排序部分,找出是否存在比current大的节点,若存在,则将该节点的前驱节点记为prev,退出遍历。
3.若上述节点存在,则将current插入到已排序部分,注意在此之前要将tail->next指向正确的节点。
4.若上述节点不存在,则直接将tail向后移动一位即可。
5.循环2-4步,直至tail移动到最后一个节点。注意在每次循环的开始要将current移动到tail->next的位置。
代码如下:

void InsertSort(Lnode *head)
{
	Lnode *current, *prev, *tail;
	prev = current = tail = head;
	while (tail->next != NULL) {
		prev = head;
		current = tail->next; //current is the begin of unsorted part
		while (prev->next != current && prev->next->data < current->data) 
			prev = prev->next; //Find first element which is bigger than current in sorted part
		if (prev != tail) { //There exists an element in sorted part which is bigger than current
			tail->next = current->next;
			current->next = prev->next;
			prev->next = current;
		}
		else //Every sorted element is smaller than current
			tail = current; //tail is the end of sorted part
	}	
}

由于单链表只能从前向后找,在实现上与数组有一些不同之处,但是基本思想是一样的。下面这个动图是从后往前找到插入点,供参考。
insertsort

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值