基数排序

//RadixSort.h

#ifndef _RADIXSORT_H_
#define _RADIXSORT_H_

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "List\List.h"

#define SIZE	15


typedef int Element;
typedef Element ListType[SIZE];

void CreateRandom(ListType L, int n);
void print(ListType L, int n);

//基数排序
void RadixSort(ListType L, int n);

#endif //_RADIXSORT_H_

//RadixSort.c

#include "RadixSort.h"

void CreateRandom(ListType L, int n)
{
	int i = 0;
	srand((unsigned)time(NULL));

	for (i = 0; i < n; ++i)
	{
		L[i] = rand() % 0x7F;
	}
}

void print(ListType L, int n)
{
	int i = 0;
	for (i = 0; i < n; ++i)
	{
		printf("%d\t", L[i]);
	}
	printf("\n");
}

/******************************************************
基数排序不需要无序序列直接进行关键字间的比较,而是根据每个关
键字的的信息再借助桶(桶间有序)对各序列中的元素按照一定的关系
进行分配(类似哈希表),分配到桶上再收集(由于桶间本身有序,且分
配的关系一定,必然分配到桶上的序列按照一定的方式去查看也是有
序的)时必然也是按一定的方式有序,对每个关键字重复分配收集过程
后排序完成。

分配后的收集时,注意先入先出以保证稳定性
为保证可扩展性,应使用链式存储结构作为桶
******************************************************/
static int GetKey(Element L, int p)					//求某个位置p上的关键字
{
	int val = 0;

	while (p >= 0)
	{
		val = L % 10;
		L /= 10;
		p--;
	}
	return val;
}

static void Distribute(ListType L, List list[10], int p, int n)
{
	int i = 0, pos = 0;
	for(i = 0; i < n; ++i)				//对所有元素按照关键字进行分配
	{
		pos = GetKey(L[i], p);
		push_back(&list[pos], L[i]);	
	}
}

static void Collect(ListType L, List list[10])
{
	int i = 0, j = 0, len = 0, k = 0;
	List *p = NULL;

	for (i = 0; i < 10; ++i)			//按桶的顺序收集元素,收集完成后,无序序列对关键字有序
	{
		p = &list[i];
		len = length(*p);
		for (k = 0; k < len; ++k)
			pop_front(p, &L[j++]);
	}
}

void RadixSort(ListType L, int n)
{
	int i = 0, j = 0, m = 0;
	Element Temp;
	List list[10];					//由于是10进制的数字,每个位上只可能是0~9, 所以采用10个链表作为桶

	for(i = 0; i < 10; ++i )
	{
		init(&list[i]);				//初始化
	}

	for(i = 0; i < n; ++i)			//在序列中查找最大元素
	{
		if( L[j] < L[i] )
			j = i;
	}

	Temp = L[j];
	while (Temp > 0)				//计算最大数的最高位,以得到关键字个数
	{
		Temp /= 10;
		m++;
	}

	for(j = 0; j < m; ++j)			//LSD 最低位优先
	{
		Distribute(L, list, j, n);	//按照关键字对序列中每个元素进行分配
		Collect(L, list);			//依照通的顺序收集元素
	}
}

//main.c

#include "RadixSort.h"

int main(int argc, char **argv)
{
	ListType List ={ 0 };
	int n = sizeof(List) / sizeof(Element);

	CreateRandom(List, n);
	printf("排序前\n");
	print(List, n);

	RadixSort(List, n);
	
	printf("排序后\n");
	print(List, n);

	system("pause");
	return 0;
}

//List.h

/***************************************** 
头插      尾插      显示      头删      尾删       
按值插入    按位置插入       查找      长度               
逆序      清除      摧毁      初始化 排序 
按位置删除       按值删除 
****************************************/  
  
  
#ifndef LIST_H_  
#define LIST_H_  
#include <stdio.h>  
#include <stdbool.h>
  
typedef int ElementType;  
  
  
typedef struct Node  
{  
    ElementType data;  
    struct Node *next;  
}Node, *pNode;  
  
typedef struct List  
{  
    Node *first;    //指向头结点  
    Node *last;     //指向最后一个节点,用于在某些时候避免不必要的遍历  
    int   size;     //链表除头结点的个数  
}List, *pList;  
  
  
bool init(List *mylist);  
bool push_front(List *mylist, ElementType e);  
bool push_back(List *mylist, ElementType e);  
bool show(List mylist);  
bool pop_front(List* mylist, ElementType *e);  
bool pop_back(List* mylist, ElementType *e);  
bool insert_val(List *mylist, ElementType e);  
bool insert_pos(List *mylist, int i, ElementType e);  
Node *find(List mylist, ElementType e, bool precursor);  
int  length(List mylist);  
bool reverse(List *mylist);  
bool clear(List *mylist);  
bool destroy(List *mylist);  
bool sort(List *mylist);  
bool delete_pos(List *mylist, int i, ElementType *e);  
bool delete_val(List *mylist, ElementType e);  
  
#endif //LIST_H_  

//List.c

#include "List.h"  
#include "stdlib.h"  
/************************* 
在操作线性表时,注意每个结构体成员的值 
注意边界条件,如涉及删除操作,必然先判断链表成员情况 
按位插入时考虑位置、等 
另外注意不同线性表各自的不同特性对操作的影响 
稍加修改便可实现泛型数据结构 
代码中有很多重复的代码片段,可以将它们单独封装成内联函数并在需要时调用。。。。。 
**************************/  
bool init(List *mylist)  
{  
    mylist->last = mylist->first = (Node *)malloc(sizeof(Node));  
    if( NULL == mylist->first )  
    {  
        return false;  
    }  
    mylist->first->next = NULL;   //注意新节点的指针域  
    mylist->first->data = -1;  
    mylist->size = 0;  
    return true;  
}  
  
bool push_front(List *mylist, ElementType e)  
{  
    Node *p = (Node *)malloc(sizeof(Node));  
    if( NULL == p )  
        return false;  
    p->next = NULL;  
    p->data = e;  
  
    p->next = mylist->first->next;  
    mylist->first->next = p;  
    if( 0 == mylist->size )    
        mylist->last = p;    //链表为空时,新节点也是尾节点  
    mylist->size++;  
    return true;  
}  
  
bool push_back(List *mylist, ElementType e)  
{  
    Node *s = NULL;  
    Node *p = (Node *)malloc(sizeof(Node));  
    if( NULL == p )  
        return false;  
    p->data = e;  
    p->next = NULL;  
  
    mylist->last->next = p;         
    mylist->last = p;            //注意更改尾指针  
    mylist->size++;  
    return true;  
}  
  
bool show(List mylist)  
{  
    Node *p = mylist.first->next;  
    while(NULL != p)  
    {  
        printf("%d->", p->data);  
        p = p->next;  
    }  
    printf("NULL\n");  
    printf("尾节点的值为%d\n", *mylist.last);  
    return true;  
}  
  
bool pop_front(List* mylist, ElementType *e)  
{  
    if( 0 == mylist->size)   //避免删除空表  
    {  
        return false;  
    }  
    Node *p = mylist->first->next;  
    mylist->first->next = p->next;  
    *e = p->data;  
    free(p);  
  
    if( 1== mylist->size )       //亦可通过比较p与last指针判断  
        mylist->last = mylist->first; //处理尾指针  
    mylist->size--;  
    return true;  
}  
  
bool pop_back(List* mylist, ElementType *e)  
{  
    if( 0 == mylist->size )  //避免删除空表  
    {  
        printf("链表为空\n");  
        return false;  
    }  
    Node *p = mylist->first;  
    while(p->next != mylist->last)  
        p = p->next;             //寻找尾节点前驱节点  
  
    *e = mylist->last->data;  
    free(mylist->last);  
    mylist->last = p;  
    p->next = NULL;  
    mylist->size--;  
    return true;  
}  
  
bool insert_val(List *mylist, ElementType e)    //此函数的先决条件:链表中已存在节点值必须有序  
{  
    if( 0 == mylist->size )  
        return push_back(mylist, e);  
    Node *v = (Node *)malloc(sizeof(Node));  
    if( NULL == v )  
        return false;  
    v->next = NULL;  
    v->data = e;  
  
    Node *p = mylist->first;  
    while(NULL != p->next && p->next->data < e)  
        p = p->next;       
    if( NULL == p->next )  
        mylist->last = p;        //尾指针  
    v->next = p->next;  
    p->next = v;  
    mylist->size++;  
    return true;  
}  
  
//指定头结点为第0个位置,在第1个位置插入,则插入完成后的第1个位置即为新节点  
bool insert_pos(List *mylist, int i, ElementType e)  
{  
    if( i < 1 )  
    {  
        printf("输入位置小于1, 已插入为第一个节点\n");  
        return push_front(mylist, e);  
    }  
    if( i > mylist->size )  
    {  
         printf("输入的位置大于链表范围,已插入为尾节点\n");  
         return push_back(mylist, e);  
    }  
  
    Node *v = (Node *)malloc(sizeof(Node));  
    if( NULL == v )  
        return false;  
    v->data = e;  
    v->next = NULL;  
  
    Node *p = mylist->first;  
    for(int j = 1; j < i; j++)  
    {  
        p = p->next;     //寻找合适的位置  
    }  
    v->next = p->next;  
    p->next = v;  
    mylist->size++;  
    return true;  
}  
  
Node  *find(List mylist, ElementType e, bool precursor) //precursor为真时返回e节点的前驱节点指针值  
{  
    if( 0 == mylist.size )  
        return NULL;  
    Node *p = mylist.first;  
    while(NULL != p->next && p->next->data != e)  
        p = p->next;  
    if( NULL == p->next )  
        return NULL;  
    else  
        return precursor ? p : p->next;  
}  
  
int  length(List mylist)  
{  
    return mylist.size;  
}  
  
//将链表分成两个链表(链表1有头结点与1节点,链表2为剩余节点的链表)后,将链表2的节点逐个头插入链表1  
bool reverse(List *mylist)  
{  
    if( 0 == mylist->size || 1 == mylist->size )  
        return true;  
    Node *p = mylist->first->next;  
    Node *q = p->next;  
  
    p->next = NULL;      //拆分链表  
    mylist->last = p;    //处理尾指针  
  
    while(NULL != q)  
    {  
        p = q;  
        q = q->next;  
        p->next = mylist->first->next;  
        mylist->first->next = p;  
    }  
    return true;  
}  
  
bool clear(List *mylist)  
{  
    if( 0 == mylist->size )  
        return true;  
    Node *p = mylist->first->next;  
    mylist->last = mylist->first; //尾指针  
    while( NULL != p)  
    {  
        mylist->first->next = p->next;  
        free(p);  
        p = mylist->first->next;  
    }  
    mylist->size = 0;            //!!!  
    return true;  
}  
  
bool destroy(List *mylist)  
{  
    clear(mylist);  
    free(mylist->first);  
    mylist->first = mylist->last = NULL;  
    return true;  
}  
//拆分后按序插入  
bool sort(List *mylist)  
{  
    if( 0 == mylist->size || 1 == mylist->size )  
        return true;  
    Node *p = mylist->first->next;  
    Node *q = p->next;  
    mylist->last = p;    //尾指针  
    p->next = NULL;      //拆分链表  
    Node *s = mylist->first; //s指向含头结点链表  
  
    while(NULL != q)    //q指向不含头结点链表  
    {  
        while(NULL != s->next && s->next->data < q->data)      
        {  
            s = s->next;  
        }  
        if( NULL == s->next )      
            mylist->last = q;    //处理尾指针  
        p = q;    
        q = q->next;  
        p->next = s->next;  
        s->next = p;  
        s = mylist->first;       //!!!!!!!!!!!!!!!!!!!!  
    }  
    return true;  
}  
  
bool delete_pos(List *mylist, int i, ElementType *e)  
{  
    int j = 0;  
    Node *p = mylist->first;  
    Node *q = NULL;  
    if( 0 == mylist->size )  
    {  
        printf("链表为空\n");  
        return false;  
    }  
    if( i < 1 || i > mylist->size )  
    {  
        printf("指定的 删除位置不合法,请重新选择\n");  
        return false;  
    }  
    for(j = 1; j < i; j++)  
    {  
        p = p->next;  
    }  
    q = p->next;  
    p->next = q->next;  
    *e = q->data;  
    if( NULL == q )  
        mylist->last = p;        //  尾  
    free(q);  
    mylist->size--;  
    return true;  
}  
  
bool delete_val(List *mylist, ElementType e)  
{  
    Node * p = NULL, *q = NULL;  
    if( NULL == ( p = find(*mylist, e, true)) )  
    {  
        printf("需要删除的节点不存在\n");  
        return false;  
    }  
    q = p->next;  
    p->next = q->next;  
    if( NULL == q )  
        mylist->last = p;        //  尾  
    free(q);  
    mylist->size--;  
    return true;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值