数据结构:线性表顺序表示和实现

本文详细介绍使用C语言实现线性表的顺序表示算法,包括初始化、销毁、清空、判断空表、获取长度、获取元素、定位元素、插入、删除、遍历等功能,并演示如何通过实例操作线性表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

内容:数据结构第二章线性表顺序表示算法C语言代码实现
参考书:数据结构严书,高一凡数据结构与算法
测试软件:Visual Studio 2017
c1.h:

#ifndef __C1_H
//#define __C1_H

//c1.h(头文件名)
#include <string.h>     //字符串函数头文件
#include <ctype.h>      //字符函数头文件
#include <malloc.h>     //malloc()等
#include <limits.h>     //INT_MAX等
#include <stdio.h>      //标准输入输出头文件,包括EOF( = ^Z 或F6),NULL等
#include <stdlib.h>     //atoi(), exit()
#include <io.h>         //eof()
#include <math.h>       //数学函数头文件,包括floor(), ceil(), abs()等
#include <sys/timeb.h>  //ftime()
#include <stdarg.h>   //提供宏va_start, va_arg, va_end,用于存取变长参数表
//函数结果状态代码。在严书第十页
#define TURE 1
#define FALSE 0
#define OK 1
#define ERROR 0
//#define INFESIBLE -1
//#define OVERFLOW -2   因为在math.h中已定义OVERFLOW的值为3,故去掉此行
typedef int Status; //Status是函数的;类型其值是函数结果状态代码,如OK等
typedef int Boolean; //Boolean是布尔类型,其值是TRUE或FALSE,第7、8、9章用到
typedef int ElemType;


#endif // !__C1_H
#pragma once

c2-1.h:

#ifndef C2-1_H
//#define C2-1_H
#define LIST_INIT_SIZE 10 //线性表存储空间的初始分配量
#define LIST_INCREMENT 2  //线性表存储空间的分配增量
#include "c1.h"

struct SqList
{
	ElemType * elem; //存储空间基址
	int length;		 //当前长度
	int listsize;    //当前分配的存储容量(以sizeof(ElemType)为单位)
};

#endif // !C2-1_H
#pragma once

bo2-1.h:

#ifndef BO2-1_H

#include "c1.h"
#include "c2-1.h"

void InitList(SqList &L)     //动态构造一个空的顺序表
{
	L.elem = (ElemType *)malloc(LIST_INIT_SIZE * sizeof(ElemType));
	if (!L.elem)
		exit(OVERFLOW); //分配失败退出
	L.length = 0;       //初始存储容量
	L.listsize = LIST_INIT_SIZE;
}

void DestroyList(SqList &L)   //销毁线性表
{
	free(L.elem);   //释放内存
	L.elem = NULL;  //删除后是elem指向NULL
	L.length = 0;
	L.listsize = 0;
}

void ClearList(SqList &L)    //将L置为空表
{
	L.length = 0;
}

Status ListEmpty(SqList L)    //判断L是否为空表
{
	if (L.length == 0)
		return TRUE;
	else
		return FALSE;
}

int ListLength(SqList L)    //得到L的长度
{
	return L.length;
}

Status GetElem(SqList L, int i, ElemType &e)  //返回线性表L中的第i个元素
{
	if ((i < 1) || (i > L.length))
	{
		return ERROR;
	}
	e = L.elem[i-1];
	//e = *(L.elem + i - 1);
	return OK;
}

int LocateElem(SqList L, ElemType e, Status(* compare)(ElemType, ElemType))
{
	//返回L中第一个与e满足关系compare()的数据元素的位序
	int i = 1;
	ElemType * p = L.elem;
	while (i <= L.length && !compare(*p++, e))
		i ++;
	if (i <= L.length)
		return i;     //返回符合条件的次序
	else
		return 0;
}
Status PriorElem(SqList L, ElemType cur_e, ElemType & pre_e)
{
	//若cur_e是L中的元素。且不是第一个,则用pre_e返回他的直接前驱,若不是,则操作失败
	int i = 2;
	ElemType * p = L.elem + 1;
	while (i <= L.length && *p != cur_e)
	{
		p++;
		i++;
	}
	if (i > L.length)
	{
		return ERROR;
	}
	else
	{
		pre_e = *(p - 1);
		pre_e = *--p;
		return OK;
	}
}

Status NextElem(SqList L, ElemType cur_e, ElemType &next_e)
{
	//若cur_e是L的数据元素,且不是第一个,则用pre_e返回它的前驱
	int i = 1;
	ElemType * p = L.elem;
	while (i < L.length && *p != cur_e)
	{
		p++;
		i++;
	}
	if (i == L.length)
	{
		return ERROR;
	}
	else
	{
		next_e = *++p;
		return OK;
	}
}

Status ListInsert(SqList &L, int i, ElemType e)  //在L的第i的位置插入e
{
	ElemType *newbase, *p, *q;
	if (i < 1 || i > L.length+1)   //插入位置无效
	{
		return ERROR;
	}
	if (L.length == L.listsize)      //空间不足,从新分配   
	{
		newbase = (ElemType *)realloc(L.elem, (LIST_INCREMENT + L.listsize) * sizeof(ElemType));
		if (!newbase)
		{
			exit(OVERFLOW);
		}
		L.elem = newbase;     //指向重新分配的空间
		L.listsize = LIST_INCREMENT + L.listsize;
	}
	q = L.elem + i - 1;
	for (p = L.elem + L.length - 1; p >= q; p--)
	{
		*(p+1) = *p;
	}
	*q = e;  //插入e
	L.length++; //表长记得+1
	return OK;
}

Status ListDelete(SqList &L, int i, ElemType e)   //删除第i个元素
{
	ElemType *p, *q;
	if (i < 1 || i > L.length)   //插入位置无效
	{
		return ERROR;
	}
	p = L.elem + i - 1;
	q = L.elem + L.length - 1;
	e = *p;             //将删除的值赋给e
	for (p++; p <= q; p++)
	{
		*(p-1) = *p;
	}
	L.length--;
	return OK;
}

void ListTraverse(SqList L, void( * visit)(ElemType &))
{
	//一次对L的每个数据元素调用函数visit(),visit()的形参加&,表明可通过调用visist()改变元素的值
	ElemType *p = L.elem;
	int i;
	for (i = 1; i <= L.length; i++)
	{
		visit(*p++);
	}
	printf("\n");
}



#endif // !BO2-1_H
#pragma once

func2-2.h:

#ifndef FUNC2-2_H
//#define FUNC2-2_H

#include "c1.h"
#include "c2-1.h"
#include "bo2-1.h"

Status equal(ElemType c1, ElemType c2)  //判断是否相等
{
	if (c1 == c2)
		return TRUE;
	else
		return FALSE;
}
int comp(ElemType a, ElemType b)
{
	if (a == b)
		return 0;
	else
		return (a-b)/abs(a-b);  //如1-2 / |1-2| = -1
}
void print(ElemType c)
{
	printf(" %d ", c);
}
void print1(ElemType &c)
{
	printf(" %d ", c);
}
void print2(ElemType c)
{
	printf(" %c ", c);
}
#endif // !FUNC2-2_H
#pragma once

main2-1h:

// 顺序表.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "c1.h"
#include "c2-1.h"
#include "func2-2.h"
#include "algo2-1.h"

Status sq(ElemType c1, ElemType c2)    //作为LocateElem()函数的实参
{
	if (c1 == c2 * c2)
		return true;
	else
		return false;
}
void db1(ElemType &c)  //作为ListTraverse()函数的实参
{
	c *= 2;
}

int main()
{
	SqList L;
	ElemType e = 0, e0 = 0;
	Status i;
	int j, k;

	InitList(L);
	printf("初始化L后,L.length = %d,L.listsize = %d, L.Elem = %u\n", L.length, L.listsize, L.elem);
	for (j = 1; j <= 5; j++)
	{
		i = ListInsert(L, 1, j);
	}
	printf("在L的表头一次插入1~5后,*Elem =");
	for (j = 1; j <= 5; j++)
	{
		printf(" %d ", L.elem[j-1]);
	}

	printf("\n调用ListTraverse()函数后,依次输出表L的值:");
	ListTraverse(L, print1);

	i = ListEmpty(L);
	printf("L.length = %d,L.listsize = %d(不变),", L.length, L.listsize);
	printf("L.elem = %u,L是否空?i = %d(1:是 0:否)\n", L.elem, i);

	ClearList(L);
	i = ListEmpty(L);
	printf("清空L后,L.length = %d,L.listsize = %d(不变),", L.length, L.listsize);
	printf("L.elem = %u,L是否空?i = %d(1:是 0:否)\n", L.elem, i);

	for (j = 1; j <= 10; j++)
	{
		ListInsert(L, j, j);
	}
	printf("在L的表头一次插入1~10后,*Elem =");
	ListTraverse(L, print1);

	printf("L.length = %d,L.listsize = %d, L.Elem = %u\n", L.length, L.listsize, L.elem);
	ListInsert(L, 1, 0);
	printf("在L的表头插入0后,L.length = %d,L.listsize = %d(改变),L.Elem = %u(可能改变)\n", L.length, L.listsize, L.elem);

	GetElem(L, 5, e);
	printf("第5个元素的值为%d\n", e);

	for (j = 10; j <= 11; j++)
	{
		k = LocateElem(L, j, equal);   //查找与j相同的元素并返回其次序
		if (k)
		{
			printf("第%d个元素的值是:%d,", k, j);
		}
		else
		{
			printf("没有值为%d的值\n",j);
		}
	}

	for (j = 3; j <= 4; j++)
	{
		k = LocateElem(L, j, sq);   //查找与j的平方相同的元素并返回其次序
		if (k)
		{
			printf("第%d个元素的值是%d的平方,", k, j);
		}
		else
		{
			printf("没有值为%d的平方的值\n", j);
		}
	}

	for (j = 1; j <= 2; j++)  //测试前两个数据
	{
		GetElem(L, j, e0);
		i = PriorElem(L, e0, e);  //e0的前驱赋给e
		if (i == ERROR)
		{
			printf("元素%d无前驱,", e0);
		}
		else
		{
			printf("元素%d的前驱为:%d\n", e0, e);
		}
	}

	for (j = ListLength(L) - 1; j <= ListLength(L); j++)
	{
		GetElem(L, j, e0);
		i = NextElem(L, e0, e);
		if (i == ERROR)
		{
			printf("元素%d无后继\n", e0);
		}
		else
		{
			printf("元素%d的后继为:%d,", e0, e);
		}
	}
	k = ListLength(L);
	for (j = k + 1; j >= k; j--)
	{
		i = ListDelete(L, j, e);
		if (i == ERROR)
		{
			printf("删除第%d个元素失败。", j);
		}
		else
		{
			printf("删除第%d个元素成功,其值为%d", j, e);
		}
	}

	ListTraverse(L, db1);
	printf("L的元素值加倍后,L =");
	ListTraverse(L, print1);
	DestroyList(L);
	printf("销毁L后,L.length = %d,L.listsize = %d, L.elem = %u\n", L.length, L.listsize, L.elem);
    return 0; 
}

【附】 La和Lb按序合并到Lc算法实现(在上面的基础上添加algo2-1.h,再修改main()):
algo2-1h:

#ifndef ALGO2-1_H
#include "c1.h"
#include "c2-1.h"

void MergeList(SqList La, SqList Lb, SqList &Lc)
{
	//已知顺序线性表La和Lb的元素按值非递减排列
	//归并La和Lb得到新的顺序线性表Lc,Lc的元素也按值非递减排列(不改变La和Lb)
	ElemType *pa, *pb, *pa_last, *pb_last, *pc;
	pa = La.elem;
	pa_last = La.elem + La.length - 1;
	pb = Lb.elem;
	pb_last = Lb.elem + Lb.length - 1;
	Lc.listsize = Lc.length = La.length + Lb.length;
	pc = Lc.elem = (ElemType *)malloc(sizeof(ElemType) * Lc.listsize);
	if (!pc)
		exit(OVERFLOW);
	while (pa <= pa_last && pb <= pb_last)
	{
		if (*pa <= *pb)
		{
			*pc++ = *pa++;
		}
		else
		{
			*pc++ = *pb++;
		}
	}
	while (pa <= pa_last) //La中剩下的且都大于Lb中元素的元素
		*pc++ = *pa++;
	while (pb <= pa_last) //La中剩下的且都大于Lb中元素的元素
		*pc++ = *pb++;
}
#endif // !ALGO2-1_H
#pragma once

main2-1h:

// 顺序表.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "c1.h"
#include "c2-1.h"
#include "func2-2.h"
#include "algo2-1.h"

Status sq(ElemType c1, ElemType c2)    //作为LocateElem()函数的实参
{
	if (c1 == c2 * c2)
		return true;
	else
		return false;
}
void db1(ElemType &c)  //作为ListTraverse()函数的实参
{
	c *= 2;
}

int main()  //测试algo2-1
{
	SqList La, Lb, Lc;
	int j;
	InitList(La);
	for (j = 1; j <= 5; j++)
		ListInsert(La, j, j);
	printf("La = ");
	ListTraverse(La, print1);
	printf("\n");

	InitList(Lb);
	for (j = 1; j <= 5; j++)
		ListInsert(Lb, j, 2*j);
	printf("Lb = ");
	ListTraverse(Lb, print1);
	printf("\n");

	MergeList(La, Lb, Lc);
	printf("Lc = ");
	ListTraverse(Lc, print1);
	printf("\n");

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值