数据结构:顺序表(SqList)基本操作的算法描述(C语言)

作者在学习数据结构时,发现鲜有完全按照 C 语言描述的算法操作,这让习惯于写 .c 而不是 .cpp 的初学者很是头疼。本文将基于 C 语言描述算法操作,如有错漏还望大佬们指正。


前言

本文将按照严惠敏所著《数据结构(C语言版)》所做的函数原型声明进行算法描述,由于C语言不支持函数参数中出现取地址符,我将函数参数更改为指针,调用函数时需要使用一级指针。新增了打印函数 PrintList; 顺序表的基本操作调用示例将在本文后给出。


一、顺序表基本操作的函数声明

//构造一个空的线性表 L 
extern Status InitList(SqList *L);
//销毁线性表 L 
extern Status Destroylist(SqList *L);
//将 L 重置为空表
extern Status ClearList(SqList *L);
//若 L 为空表,则返回 TRUE,否则返回 FALSE 
extern Status ListEmpty(SqList L);
//返回 L 中数据元素个数
extern int ListLength(SqList L);
//用 e 返回 L 中第 i 个数据元素的值
extern Status GetElem(SqList L, int i, ElemType *e);
//返回 L 中第一个与 e 满足关系 compare() 的数据元素的位序,若这样的数据元素不存在,则返回 0
extern int LocateElem(SqList L, ElemType e, Status (*compare)(ElemType, ElemType));
//若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱,否则操作失败,pre_e 无定义
extern Status PriorElem(SqList L, ElemType cur_e, ElemType *pre_e);
//若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继,否则操作失败,next_e 无定义
extern Status NextElem(SqList L, ElemType cur_e, ElemType *next_e);
//在 L 中第 i (1 <= i <= ListLength(L) + 1) 个位置之前插入新的数据元素 e,L 的长度加 1
extern Status ListInsert(SqList *L, int i, ElemType e);
//删除 L 的第 i (1 <= i <= ListLength(L) + 1) 个数据元素,并用 e 返回其值,L 的长度减 1
extern Status ListDetele(SqList *L, int i, ElemType *e);
//打印线性表 L
extern Status PrintList(SqList L);
//将所有在线性表 Lb 中但不在 La 中的数据元素插入到 La 中
extern Status UnionList(SqList *La, SqList Lb);
//归并两个非递减排列的线性表 La、Lb 至 Lc,Lc也是非递减排列的
extern Status MergeList(SqList La, SqList Lb, SqList *Lc);

二、顺序表基本操作的完整描述

/* 顺序表 */
#include <stdio.h>
#include <stdlib.h>
#define TRUE  			1
#define FALSE 			0
#define OK    			1
#define ERROR 			0
#define INFEASIBLE 		-1
#define OVERFLOW   		-2
#define LIST_INIT_SIZE 	100
#define LISTINCREMENT  	10
#define EQUAL			0
#define LOWER			1
#define HIGHER			2

typedef int Status;
typedef int ElemType;
typedef struct {
	ElemType* elem; //存储空间基址
	int length;   //当前长度
	int listsize;//当前分配的存储容量
} SqList;

//构造一个空的线性表 L 
extern Status InitList(SqList* L);
//销毁线性表 L 
extern Status Destroylist(SqList* L);
//将 L 重置为空表
extern Status ClearList(SqList* L);
//若 L 为空表,则返回 TRUE,否则返回 FALSE 
extern int ListEmpty(SqList L);
//返回 L 中数据元素个数
extern int ListLength(SqList L);
//用 e 返回 L 中第 i 个数据元素的值
extern Status GetElem(SqList L, int i, ElemType* e);
//返回 L 中第一个与 e 满足关系 compare() 的数据元素的位序,若这样的数据元素不存在,则返回 0
extern int LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType));
//若 cur_e 是 L 的数据元素,且不是第一个,则用 pre_e 返回它的前驱,否则操作失败,pre_e 无定义
extern Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e);
//若 cur_e 是 L 的数据元素,且不是最后一个,则用 next_e 返回它的后继,否则操作失败,next_e 无定义
extern Status NextElem(SqList L, ElemType cur_e, ElemType* next_e);
//在 L 中第 i (1 <= i <= ListLength(L) + 1) 个位置之前插入新的数据元素 e,L 的长度加 1
extern Status ListInsert(SqList* L, int i, ElemType e);
//删除 L 的第 i (1 <= i <= ListLength(L) + 1) 个数据元素,并用 e 返回其值,L 的长度减 1
extern Status ListDetele(SqList* L, int i, ElemType* e);
//打印线性表 L
extern Status PrintList(SqList L);
//将所有在线性表 Lb 中但不在 La 中的数据元素插入到 La 中
extern Status UnionList(SqList* La, SqList Lb);
//归并两个非递减排列的线性表 La、Lb 至 Lc,Lc也是非递减排列的
extern Status MergeList(SqList La, SqList Lb, SqList* Lc);

Status 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;
	return OK;
}//InitList

Status Destroylist(SqList* L) {
	free(L->elem);
	L->elem = NULL;
	L->length = 0;
	L->listsize = 0;
	return OK;
}//Destroylist

Status ClearList(SqList* L) {
	free(L->elem);
	L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));
	if (!L->elem)
		exit(OVERFLOW);
	L->length = 0;
	L->listsize = LIST_INIT_SIZE;
	return OK;
}//ClearList

int ListEmpty(SqList L) {
	return L.length == 0 ? TRUE : FALSE;
}//ListEmpty

int ListLength(SqList L) {
	return L.length;
}//ListLength

Status GetElem(SqList L, int i, ElemType* e) {
	if (i < 1 || i > L.length || L.length == 0)
		return ERROR;
	*e = L.elem[i - 1];
	return OK;
}//GetElem

int LocateElem(SqList L, ElemType e, Status(*compare)(ElemType, ElemType)) {
	int i = 1;
	ElemType* p = L.elem;
	while (i < L.length && !(*compare)(*p++, e)) ++i;
	if (i <= L.length) return i;
	else return 0;
}//LocateElem

Status PriorElem(SqList L, ElemType cur_e, ElemType* pre_e) {
	ElemType* pre = L.elem;
	for (ElemType* p = L.elem; p <= &(L.elem[L.length - 1]); p++) {
		if (*p == cur_e) {
			*pre_e = *pre;
			return OK;
		}
		pre = p;
	}
	return ERROR;
}// PriorElem

Status NextElem(SqList L, ElemType cur_e, ElemType* next_e) {
	ElemType* nxt = L.elem + 1;
	for (ElemType* p = L.elem; p < &(L.elem[L.length - 1]); p++, nxt++) {
		if (*p == cur_e) {
			*next_e = *nxt;
			return OK;
		}
	}
	return ERROR;
}// NextElem

Status ListInsert(SqList* L, int i, ElemType e) {
	if (i < 1 || i > L->length + 1) return ERROR;
	if (L->length >= L->listsize) {
		ElemType* newbase;
		newbase = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(ElemType));
		if (!newbase) exit(OVERFLOW);
		L->elem = newbase;
		L->listsize += LISTINCREMENT;
	}
	ElemType* p, * q;
	q = &(L->elem[i - 1]);
	for (p = &(L->elem[L->length - 1]); p >= q; --p) *(p + 1) = *p;
	*q = e;
	++L->length;
	return OK;
}// ListInsert

Status ListDetele(SqList* L, int i, ElemType* e) {
	if (i < 1 || i > L->length) return ERROR;
	ElemType* p, * q;
	p = &(L->elem[i - 1]);
	*e = *p;
	q = L->elem + L->length - 1;
	for (++p; p <= q; ++p) *(p - 1) = *p;
	--L->length;
	return OK;
}// ListDelete

Status ListTraverse(SqList L, void(*visit)(ElemType*)) {
	ElemType* p;
	int i;
	p = L.elem;
	for (i = 1; i <= L.length; i++)
		visit(p++);
	printf("\n");
	return OK;
}// ListTraverse

Status PrintList(SqList L) {
	ElemType e = 0;
	for (int i = 1; i <= L.length; i++) {	
		GetElem(L, i, &e);
		printf("%d ", e);
	}
	printf("\n");
	return OK;
}// PrintList

Status UnionList(SqList* La, SqList Lb) {
	int La_len, Lb_len;
	ElemType e;
	La_len = ListLength(*La); Lb_len = ListLength(Lb);
	for (int i = 1; i < Lb_len; i++) {
		GetElem(Lb, i, &e);
		if (!LocateElem(*La, e, EQUAL))ListInsert(La, ++La_len, e);
	}
}// UnionList

Status MergeList(SqList La, SqList Lb, SqList* Lc) {
	InitList(Lc);
	int i, j, k, La_len, Lb_len;
	ElemType* a, * b;
	a = (ElemType*)malloc(sizeof(ElemType));
	b = (ElemType*)malloc(sizeof(ElemType));
	i = j = 1; k = 0;
	La_len = ListLength(La); Lb_len = ListLength(Lb);
	while (i <= La_len && j <= Lb_len) {
		GetElem(La, i, a + i); GetElem(Lb, j, b + j);
		if (a[i] <= b[j]) { ListInsert(Lc, ++k, a[i]); ++i; }
		else { ListInsert(Lc, ++k, b[j]); ++j; }
	}
	while (i <= La_len) {
		GetElem(La, i++, a + i); ListInsert(Lc, ++k, a[i]);
	}
	while (j <= Lb_len) {
		GetElem(Lb, j++, b + j); ListInsert(Lc, ++k, b[j]);
	}
}// MergeList

三、调用示例

int main()
{
	SqList L;
	InitList(&L);
	printf("ListEmpty: %d\n", ListEmpty(L));
	ListInsert(&L, 1, 1);
	ListInsert(&L, 2, 2);
	ListInsert(&L, 3, 3);
	ListInsert(&L, 4, 4);
	ListInsert(&L, 5, 6);
	PrintList(L);
	return 0;
}

终端输出结果如下:

ListEmpty: 1
1 2 3 4 6 

总结

以上是顺序表的基本操作的算法描述,更多数据结构的算法描述还在更新中,敬请关注作者专栏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值