内部排序

common.h

#ifndef	_COMMON_H_
#define	_COMMON_H_

#define TRUE        1
#define FALSE       0
#define OK          1
#define ERROR       0
#define INFEASIBLE  -1
#define OVERFLOW    -2

typedef int Status;  

//Status Equal(int a, int b);

#endif

SqList.h

#ifndef _SQLIST_H_
#define _SQLIST_H_

#include "common.h"
#include "Sorting.h"


Status PrintElement(ElemType e);

Status InitList_Sq(SqList *L);

Status ListScanf_Sq(SqList *L);

Status Traverse(SqList *L, Status (* Visit)(ElemType e));


#endif


Sorting.h
#ifndef _SORTING_H_
#define _SORTING_H_

#define MAXSIZE 10		//顺序表的最大长度

typedef int KeyType;

typedef char Name[20];
typedef int  Score;

typedef struct
{
	KeyType		key;		//关键字项
	Name		name;
	Score		score;
}RecordType;				//记录类型

typedef struct
{
	RecordType	 r[MAXSIZE+1];	//r[0]闲置或用作哨兵单元
	int			 length;		//顺序表长度
}SqList;					//顺序表类型

#define ElemType  RecordType	//为了保持与以前写得程序的命名一致性,所以作此宏定义,其实完全也可以直接使用RecordType
//有的时候想要用到别的工程的一段代码,在将别的工程代码移植过来时,常常需要修改一些东西,有没有什么办法可以让少做修改(甚至不修改)而直接应用。


//对两个关键字的比较约定为如下的宏定义  
//>>>对数值型关键字  
#define EQ(a,b) ((a) == (b))  
#define LT(a,b) ((a) < (b))  
#define LQ(a,b) ((a) <= (b))  
//...  
  
//>>>对字符串型关键字  
//#define EQ(a,b)   (!strcmp((a),(b)))  
//#define LT(a,b)   (strcmp((a),(b))<0)  
//#define LQ(a,b)   (strcmp((a),(b))<=0)  
//...  

#endif


SqList.c
#include "common.h"
#include "Sorting.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"

Status PrintElement(ElemType e)  
{
	printf("%-3d ",e.key);  
    printf("%-16s ",e.name);    //16个字符长度是我随便定义的,当然可以改变之。  
    printf("%-3d\n",e.score);  
    return OK;  
}

Status InitList_Sq(SqList *L)
{
	L->length = MAXSIZE + 1;	//顺序表的最大长度虽然为MAXSIZE+1,但其第一个单元式闲置的,实际只用到了MAXSIZE个单元。
	return OK;
}

//说明:若想让程序具有较好的健壮性,则应当还应加入一些判定输入数据是否超出预定范围或者是否非法的判定条件,但这里都还没有。
Status ListScanf_Sq(SqList *L)
{
	SqList *p = L;
	int i = 1;	//让i从1开始是为了让表的0号单元留空。
	KeyType num;
	Score sco;
	Name name;

	if(p == NULL)
	{
		return ERROR;
	}
	scanf("%d",&num);
	if(num<0 || num>32767)
		return ERROR;
	while(num)
	{
		scanf("%s",name);
		scanf("%d",&sco);
		p->r[i].key = num;
		strcpy(p->r[i].name, name);
		p->r[i].score = sco;
		scanf("%d",&num);
		if(i++ > p->length)
		{
			printf("Search Table is full.");
            return(OVERFLOW);
		}
	}
	return OK;
}

Status Traverse(SqList *L, Status (* Visit)(ElemType e))
{  
    int i = 1;  //查找表的0号单元被留空  
    printf("\n>>>>>>>>>>>>>>>>>output start>>>>>>>>>>>>>>>>>\n");  
	while(L->r[i].key>0 && L->r[i].key<32767 && i<L->length)   //32767是int型数的最大值,当然实际应用应根据实际情况采取适当限定措施。
    {  
		Visit(L->r[i]);
        i++;  
    }  
    printf("\n>>>>>>>>>>>>>>>>>output end>>>>>>>>>>>>>>>>>\n\n");  
    return OK;  
}

Sorting.c

#include "common.h"
#include "Sorting.h"

//直接插入排序
Status StrInsertSort(SqList *L)
{
	int i,j;
	for(i=2; i<=L->length; ++i)
	{
		//这个判断是因为:有的时候虽然定义了顺序表的最大长度,但并没有存入那么多的记录进去,这时候如果光靠for循环中i<=L->length条件来判断是不行的。所以这里加入了下面的这个判断条件。
		if(L->r[i].key>0 && L->r[i].key<32767)
		{
			if(LT(L->r[i].key, L->r[i-1].key))	//如果左参数小于右参数
			{
				L->r[0] = L->r[i];		//复制为哨兵
				L->r[i] = L->r[i-1];
				for(j=i-2; LT(L->r[0].key, L->r[j].key); --j)
					L->r[j+1] = L->r[j];
				L->r[j+1] = L->r[0];
			}
		}
	}
	return OK;
}

//拆半插入排序
Status BinInsertSort(SqList *L)
{
	int i, j, middle, low, high;
	for(i=2; i<=L->length; ++i)
	{
		//加入这个判断的原因同“直接插入排序StrInsertSort()”
		if(L->r[i].key>0 && L->r[i].key<32767)
		{
			L->r[0] = L->r[i];		//将L->r[i]暂存到L->r[0]
			low = 1;
			high = i - 1;
			//在r[low..high]中拆半查找有序插入的位置
			while(low <= high)
			{
				middle = (low + high)/2;		//拆半
				if(LT(L->r[0].key, L->r[middle].key))
					high = middle - 1;		//插入点在低半区
				else
					low = middle + 1;		//插入点在高半区
			}
			//记录后移
			for(j=i-1; j>=high+1; --j)
				L->r[j+1] = L->r[j];
			L->r[high+1] = L->r[0];		//插入
		}
	}
	return OK;
}

main.c

#include "Sorting.h"
#include "SqList.h"
#include "stdio.h"

void main(void)
{
	SqList list;
	InitList_Sq(&list);
	ListScanf_Sq(&list);
	Traverse(&list, PrintElement);

	//printf("StrInsertSort");
	//StrInsertSort(&list);
	//Traverse(&list, PrintElement);
	
	printf("BinInsertSort");
	BinInsertSort(&list);
	Traverse(&list, PrintElement);
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值