链表的自底向上归并排序
应一网友要求编写了链表的自底向上归并排序程序如下:
#include <stdio.h>
#include <stdlib.h>
#define less(A,B)(A<B)
typedef int Item;
typedef struct _Qnode{
Item item;
struct _Qnode *next;
} Qnode, *link;
typedef struct
{
link head;
link tail;
} Queue;
void print_qnode(link a)
{
while(a)
{
printf(" %d",a->item);
a=a->next;
}
printf("/n");
}
void concatenate(Queue *q, Queue *p)
{
if (q->head)
{
q->tail->next=p->head;
q->tail=p->tail;
}
else
{
*q=*p;
}
}
void merge(link a,link b, Queue *q)
{
Qnode head;
link c=&head;
while((a!=NULL)&&(b!=NULL))
if(less(a->item,b->item))
{
c->next=a;
c=a;
a=a->next;
}
else
{
c->next=b;
c=b;
b=b->next;
}
c->next=(a==NULL)?b:a;
q->head=head.next;
while(c)
{
q->tail=c;
c=c->next;
}
}
link mergesort(link head, int node_size)
{
link a_head,b_head,a_tail,b_tail,remained_node;
Queue p,q;
int i,j;
if(head==NULL || head->next==NULL) return head;
remained_node=head;
//i按2的倍数增加
for(i=1; i<node_size; i*=2)
{
q.head=NULL;
do
{
a_head=a_tail=remained_node;
b_tail=remained_node->next;
//找a_tail和b_tail,使a和b中各有i个节点。
for (j=1; j<i; j++)
{
if (a_tail) a_tail=a_tail->next;
if (b_tail) b_tail=b_tail->next;
if (b_tail) b_tail=b_tail->next;
}
if (b_tail)
{
remained_node=b_tail->next;
b_tail->next=NULL;//使b与原始链断开
}
else//b中不足i个节点
{
remained_node=NULL;
}
if (a_tail)
{
b_head=a_tail->next;
a_tail->next=NULL;//使a与原始链断开
merge(a_head,b_head,&p);//a和b合并排序后存入p
concatenate(&q,&p);//p与上次合并排序的结果相连
}
else//只有a没有b
{
merge(q.head,a_head,&p);
q=p;
}
}while(remained_node);
remained_node=q.head;
}
return q.head;
}
int main()
{
int i;
int node_size;
Queue q;
link a_head,b_head,a,b,c;
a=(link)malloc(sizeof(Qnode));
b=(link)malloc(sizeof(Qnode));
a->item=10;
b->item=30;
a_head=a;
b_head=b;
node_size=0;
for(i=0;i<10;i++)
{
a->next=(link)malloc(sizeof(Qnode));
a->next->item=rand()%120;
a=a->next;
node_size++;
}
a->next=NULL;//清尾
for(i=0;i<11;i++)
{
b->next=(link)malloc(sizeof(Qnode));
b->next->item=rand()%200;
b=b->next;
node_size++;
}
b->next=NULL;//清尾
print_qnode(a_head);
print_qnode(b_head);
merge(a_head,b_head,&q);
c=q.head;
print_qnode(c);
printf("/n");
c=mergesort(c, node_size);
print_qnode(c);
return 0;
}