线性表——顺序表

线性表——顺序表

概念

采用顺序存储结构的线性表。
用一组地址连续的存储单元依次存储线性表的数据元素,以元素在计算机中物理位置来表示数据元素之间的逻辑关系。与数组类似,在于对数据元素的定义可以不局限与数字或字符,可以利用结构体完成各种不同的运算,例如复数 (a + bi) 的加减乘除。

准备工作

创建线性表 (以复数线性表为例)

typedef struct
{
    double rp, ip;
} COMPLEX;

定义COMPLEX结构体,包含rp实部, ip虚部。

typedef COMPLEX LELEMENT;

将COMPLEX定义为线性表元素LELEMENT,方便以后可以将复数线性表改为其他线性表,例如分数线性表。

#ifndef _Real_h_
#define _Real_h_

#define epsilon 1e-8

double Revise(double x);
void RealInput(double *x);
void RealOutput(double x);

int RealGt(double x, double y);
int RealGe(double x, double y);
int RealLt(double x, double y);
int RealLe(double x, double y);
int RealEq(double x, double y);
int RealNe(double x, double y);

void RealSwap(double*x, double *y);

#endif

进行实数准备工作,如实数误差修正,实数输入输出,比较大小,判断相等,交换。

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "Real.h"

double Revise(double x)
{
	if (fabs(x) < epsilon)
	{
		return 0;
	}
	else
	{
		return x;
	}
}

void RealInput(double *x)
{
	scanf("%lf", &*x);
	*x = Revise(*x); 
}

void RealOutput(double x)
{
	printf("%g", Revise(x));
}

int RealGt(double x, double y)
{
	int t=0;
	if((x-y)>=epsilon)
	{
		t=1;
	}
	return t;
}

int RealGe(double x, double y)
{
	int t=0;
	if((x-y)>=epsilon||fabs(x-y)<epsilon)
	{
		t=1;
	}
	return t;
}

int RealLt(double x, double y)
{
	int t=0;
	if((y-x)>=epsilon)
	{
		t=1;
	}
	return t;
}

int RealLe(double x, double y)
{
	int t=0;
	if((y-x)>=epsilon||fabs(x-y)<epsilon)
	{
		t=1;
	}
	return t;
}

int RealEq(double x, double y)
{
	int t=0;
	if(fabs(x-y)<epsilon)
	{
		t=1;
	}
	return t;
}

int RealNe(double x, double y)
{
	int t=0;
	if(fabs(x-y)>=epsilon)
	{
		t=1;
	}
	return t;
}

void RealSwap(double *x, double *y)
{
	double a;
	a = *x;
	*x = *y;
	*y = a;
}

进行线性表元素准备工作。

#ifndef _LElement_h_
#define _LElement_h_

#include "Complex.h"

typedef COMPLEX LELEMENT;

void LElementInput(LELEMENT *x);
void LElementOutput(const LELEMENT *x);

int LElementEq(const LELEMENT *x, const LELEMENT *y);
int LElementNe(const LELEMENT *x, const LELEMENT *y);

void LElementSwap(LELEMENT *x, LELEMENT *y);

#endif

由于复数无法比较大小,所以只有输入输出,判断相等,交换函数。

#include <stdio.h>
#include <stdlib.h>
#include "LElement.h"

void LElementInput(LELEMENT *x)
{
	ComplexInput(x); 
}

void LElementOutput(const LELEMENT *x)
{
	ComplexOutput(x);
}

int LElementEq(const LELEMENT *x, const LELEMENT *y)
{
	return ComplexEq(x, y);
}

int LElementNe(const LELEMENT *x, const LELEMENT *y)
{
	return ComplexNe(x, y);
}

void LElementSwap(LELEMENT *x, LELEMENT *y)
{
	ComplexSwap(x,  y);
}

顺序表

在开始之前,我们已经创建了Real.h、Real.c、LElement.h、LElement.c文件,现在开始构建顺序表

typedef struct
{
    int size, length;
    LELEMENT *element;
} ALIST;

包含有线性表的尺寸,线性表的长度,还有线性表元素的起始地址*element。

#ifndef _AList_h_
#define _AList_h_

#include "LElement.h"

#define AListInitSize 1024//初始尺寸
#define AListIncrement 128//新增尺寸

typedef struct
{
    int size, length;
    LELEMENT *element;
} ALIST;

void AListCreate(ALIST *list);//创建
void AListDestroy(ALIST *list);//销毁
void AListResize(ALIST *list, int size);//扩容
void AListInsert(ALIST *list, int index, const LELEMENT *element);插入
void AListOutput(const ALIST *list);//输出
void AListRemove(ALIST *list, int index, LELEMENT *element);输入
void AListClear(ALIST *list);//清空
void AListInput(ALIST *list);//输入
int AListEmpty(const ALIST *list);//判空
int AListLength(const ALIST *list);//长度
void AListSet(ALIST *list, int index, const LELEMENT *element);设置
void AListGet(const ALIST *list, int index, LELEMENT *element);获取

#endif

在程序开始前,我们需创建线性表才能开始使用,在程序结束前,应将创建的线性表销毁。在线性表初始尺寸不够容纳我们的数据元素时,我们对线性表进行扩容。而根据使用需求,有插入、输出、删除元素、输入、输出线性表、清空线性表、判断空表,获取长度,设置、获取数据元素。

#include <stdio.h>
#include <stdlib.h>
#include "AList.h"

void AListCreate(ALIST *list)
{
	list->size = AListInitSize;
	list->length = 0;
	list->element = (LELEMENT*)malloc(list->size * sizeof(LELEMENT));	
} 

void AListDestroy(ALIST *list)
{
    free(list->element);
	list->element = NULL;
	list->size = list->length = 0;
}

void AListResize(ALIST *list, int size)
{
	int i;
	LELEMENT *element;
	if (size > list->length && size != list->size)
	{
		list->size = size;
		element = (LELEMENT*)malloc(list->size * sizeof(LELEMENT));
		for (i = 0; i < list->length; i++)
		{
			element[i] = list->element[i];
		}
		free(list->element);
		list->element = element;
	}
}

void AListInsert(ALIST *list, int index, const LELEMENT *element)
{
	int i;
	if (index < 1 || index > list->length + 1)
	{
		printf("Incorrect index!\n");
	}
	else
	{
		if (list->length == list->size)
			AListResize(list, list->size + 1);
		for (i = list->length; i > index - 1; i--)
		{
			list->element[i] = list->element[i - 1];
		}
		list->element[index - 1] = *element;
		list->length++;
	}
}

void AListOutput(const ALIST *list)
{
	int i;
	putchar('(');
	for (i = 0; i < list->length; i++)
	{
		if (i)
		{
			putchar(',');
		}
		putchar(' ');
		LElementOutput(&list->element[i]);
	}
	putchar(' ');
	putchar(')');
}

void AListRemove(ALIST *list, int index, LELEMENT *element)
{
	int i;
	LELEMENT x = list->element[index - 1];
	if (index <= list->length && index > 0)
	{
		for (i = index - 1; i < list->length - 1; i++)
		{
			list->element[i] = list->element[i + 1];
		}
		list->length--;
		*element = x;
	}
	else
	{
		printf("Incorrect index!\n");
	}
}

void AListClear(ALIST *list)
{
	if (list->element != NULL)
	list->length = 0;
}

void AListInput(ALIST *list)
{
	char c;
	LELEMENT element;
	AListClear(list);
	scanf(" (");
	while (scanf(" %c", &c),c != ')')
	{
		ungetc(c, stdin);
		if (list->length)
			scanf(",");
		LElementInput(&element);
		if (list->length == list->size)
			AListResize(list ,list->size + 10);
		list->element[list->length] = element;
		++list->length;
	}
}

int AListEmpty(const ALIST *list)
{
	return !list->length; 
}

int AListLength(const ALIST *list)
{
	return list->length;
}

void AListSet(ALIST *list, int index, const LELEMENT *element)
{
	if (index <= list->length && index > 0)	list->element[index - 1] = *element;
	else	printf("Incorrect index!\n");
}

void AListGet(const ALIST *list, int index, LELEMENT *element)
{
	if (index <= list->length && index > 0)	*element = list->element[index - 1];
	else	printf("Incorrect index!\n"); 
}

完成线性表的创建和一系列对线性表的操作后,我们需要创建一操作面版提示用户如何操作

#include <stdio.h>
#include "AList.h"

int main()
{
	int index;
	LELEMENT element;
	ALIST list;
	char c;
	AListCreate(&list);
	printf("E-判空 L-长度 N-插入 R-删除 C-清空 S-设置 G-读取 I-输入 O-输出 Q-退出 > ");
	scanf(" %c", &c);
	while (c != 'q' && c != 'Q')//退出 
	{
		if (c == 'e' || c == 'E')//空 
		{
			if (AListEmpty(&list))
				printf("空表\n");
			else
				printf("非空表\n");
		}
		else if (c == 'l' || c == 'L')//长 
		{
			printf("长度: %d\n", AListLength(&list));
		}
		else if (c == 'i' || c == 'I')//输入 
		{
			printf("线性表: "); 
			AListInput(&list);
		}
		else if (c == 'n' || c == 'N')//插入 
		{
			printf("位序: ");
			scanf("%d", &index);
			printf("数据元素: ");
			LElementInput(&element);
			AListInsert(&list, index, &element);
		}
		else if (c == 'r' || c == 'R')//删除 
		{
			printf("位序: ");
			scanf("%d", &index);
			AListRemove(&list, index, &element);
			printf("数据元素: ");
			LElementOutput(&element);
			putchar('\n');
		}
		else if (c == 'c' || c == 'C')//清空 
		{
			AListClear(&list);
		}
		else if (c == 's' || c == 'S')//设置 
		{
			printf("位序: ");
			scanf("%d", &index);
			printf("数据元素: ");
			LElementInput(&element);
			AListSet(&list, index, &element);
		}
		else if (c == 'g' || c == 'G')//读取 
		{
			printf("位序: ");
			scanf("%d", &index);
			AListGet(&list, index, &element);
			printf("数据元素: ");
			LElementOutput(&element);
			putchar('\n');
		}
		else if (c == 'o' || c == 'O')//输出 
		{
			printf("线性表: ");
			AListOutput(&list);
			putchar('\n');
		}
		else
		{
			printf("不正确的选项!\n");
		}
		printf("E-判空 L-长度 N-插入 R-删除 C-清空 S-设置 G-读取 I-输入 O-输出 Q-退出 > ");
        scanf(" %c", &c);
	}
	AListDestroy(&list);
	return 0;
}


这样一个复数线性表就基本完成了。后期我们需要做其他线性表的时候,不必大刀阔斧对程序进行修改,只需要改变一些关键内容,例如将复数线性表改成分数线性表时,我们将

typedef COMPLEX LELEMENT;

改为

typedef FRACTION LELEMENT;

并将实数函数改为整数函数,并添加关于分数运算的函数,如求最大公约数

int Gcd(int x, int y)
{
	if (x || y)
	{
		int a = IntMax(x, y), b = IntMin(x, y), c;
		if (a < 0) a = -a;
		if (b < 0) b = -b;
		while (b > 0)
		{
			c = a % b;
			a = b;
			b = c;
		}
		return a;
	}
	else
	{
		return 1;
	}
}

最大公倍数

int Lcm(int x, int y)
{
	if (x < 0) x = -x;
	if (y < 0) y = -y;
	return x * y / Gcd(x, y);
}

比较大小

int LElementGt(const LELEMENT *x, const LELEMENT *y)
{
	LELEMENT a = *x, b = *y;
	return FractionGt(&a, &b);
}

int LElementGe(const LELEMENT *x, const LELEMENT *y)
{
	LELEMENT a = *x, b = *y;
	return FractionGe(&a, &b);
}

int LElementLt(const LELEMENT *x, const LELEMENT *y)
{
	LELEMENT a = *x, b = *y;
	return FractionLt(&a, &b);
}

int LElementLe(const LELEMENT *x, const LELEMENT *y)
{
	LELEMENT a = *x, b = *y;
	return FractionLe(&a, &b);
}

及其他可用于分数的运算,但不可用于复数运算的函数。

  • 12
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一颗大宝贝

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值