单链表的排序


直接插入排序

将链表断为两部分,一部分为有序链表,一部分为无序链表。逐步将无序链表中的结点按顺序插入到有序链表中。

void Listsort(LinkList head)
{
	Node *p=head->next, *pNext, *r;
	pNext = p->next;
	p->next = NULL;   //断开链表
	p = pNext;        //指针后移
	while (p)
	{
		pNext = p->next;   //pNext指向下一个结点
		r = head;          //r用来遍历单链表,寻找插入的位置
		while (r->next != NULL && r->next->date < p->date)      //在有序链表中寻找p差入的位置
			r = r->next;       //遍历
		p->next = r->next;
		r->next = p;           //插入p
		p = pNext;             //p后移一位
	}
}


转换数组

将每一个结点的地址保存到额外数组里,在对数组进行排序,安排好序的数组重新建立链表。

void Listsort(LinkList head)
{
	Node **aux,*p=head->next;      //建立二级指针aux
	int len=0,i;
	while (p)      //遍历链表,求表长
	{
		p = p->next;
		len++;
	}
	p = head->next;          
	aux = (Node**)malloc(sizeof(Node*)*len);      //开辟储存链表各结点地址的空间,将空间首地址付给aux
	for (i = 0; i < len; i++)             //将链表各节点地址保存在指针数组aux[]中
	{
		aux[i] = p;
		p = p->next;
	}

	List_insort(aux, len);                  //用数组的方式排序

	head->next=aux[0];               //连接表头
	for (i = 0; i < len-1; i++)
	{
		aux[i]->next = aux[i + 1];  //连接排好序的结点
	}
	aux[len - 1]->next = NULL;    //尾结点的指针域设为空
}

数组排序的代码(插入排序)

void List_insort(Node*a[], int n)
{
	int i, j;
	Node *temp;
	for (i = 1; i < n; i++)
	{
		j = i - 1;
		if (a[j]->date > a[i]->date)    //比较时用数据域比较
		{
			temp = a[i];
			a[i] = a[j];
			for (j = j - 1; j >= 0 && temp->date < a[j]->date; j--)
				a[j + 1] = a[j];
			a[j + 1] = temp;
		}
	}
}


冒泡排序

确定数据总量,限制循环次数,在循环中比较结点的数据并进行结点的交换。

void Listsort(LinkList head)
{
	Node *p, *q;
	int num = 0, j = 0,i;
	q = head->next;
	while (q)                    //遍历确定链表长度
	{
		q = q->next;
		num++;
	}

	for (i = 0; i < num; i++)
	{
		q = head;                //指向首元结点
		p = head->next;          //指向首元结点后的第一个结点       
		for(j=num-i-1;j>0;j--)
		{
			if (p->date > p->next->date)
			{
				q->next = p->next;

				q = p->next;
				p->next = q->next;
				q->next = p;
				p = q;                 //交换结点
			}
			q = p;                     //保证q在p前
			p = p->next;               //p后移
		}
	}
}


归并排序

  1. 用快慢指针遍历找到中间结点。
  2. 从中间结点断开,将链表分为左右两个链表,两个链表再分解(运用递归)。
  3. 当不能再分解时把两个链表合并。
  4. 继续向上合并直到链表唯一。
LinkList Listsort(LinkList start)
{
	Node *slow = start;       
	Node *fast = start;
	while (1)
	{
		if (NULL == fast)
			break;
		fast = fast->next;
		if (NULL == fast)
			break;
		fast = fast->next;
		if (NULL == fast)
			break;
		slow = slow->next;
	}
	Node *middle = slow->next;           //中间点

	if (NULL == middle)                  //只有一个结点,不用再分解
		return start;

	slow->next = NULL;                  //断开链表
	Node *l = Listsort(start);          //递归调用分解左链表
	Node *r = Listsort(middle);         //递归调用分解右链表
	Node *tmp = Combine(l, r);          //定义新指针合并左右链表
	return tmp;              //返回新指针
}

LinkList Combine(Node *left, Node *right)
{
	if (NULL == left || NULL == right)
	{
		if (NULL == left)
			return right;
		else if(NULL == right)
			return left;
	}
	else if (left->date <= right->date)
	{
		left->next = Combine(left->next, right);
		return left;
	}
	else
	{
		right->next = Combine(left, right->next);
		return right;
	}
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值