[C/C++] 数据结构-顺序表代码

利用easyx库简单实现顺序表和单链表增删改查的动画演示 EasyX 是针对 C/C++ 的图形库,可以帮助使用C/C++语言的程序员快速上手图形和游戏编程。 比如,可以用 VC + EasyX 很快的用几何图形画一个房子,或者一辆移动的小车,可以编写俄罗斯方块、贪吃蛇、黑白棋等小游戏,可以练习图形学的各种算法,等等。————百度百科 easyx的文档:https://docs.easyx.cn/en-us/intro 其实原理很简单,就是利用easyx的画圆功能,然后定位输出功能,然后加上清屏和延时函数,建议实现动画效果。 顺序表和单链表的结构体定义我就不赘述了 阅读详情

前言

定义一个枚举用于作为返回类型

typedef enum Result
{
	RES_OK, 				// 函数运行成功

	RES_BOOL_TRUE,			// 布尔值true
	RES_BOOL_FALSE,			// 布尔值false

	RES_CMP_EQUAL,			// 比较结果为相等
	RES_CMP_GREATER,		// 比较结果为大于
	RES_CMP_LESS, 			// 比较结果为小于

	RES_BASE_ERROR,			// 基础错误

	// system err
	RES_MALLOC_FAIL,		// malloc失败

	RES_PARA_ERROR,			// 入参错误
	RES_LIST_EMPTY_ERROR,	// 表为空
	RES_LIST_FULL_ERROR,	// 表已满
	RES_RANGE_ERROR			// 范围错误
} Result;

元素类型相关

// 假设元素类型是 CElemType, 根据实际情况而定

// CElemType 类型的方法
// 比较两个元素的大小
Result ElementCompare(const CElemType* e1, const CElemType* e2);

// 元素赋值
Result ElementAssignment(CElemType* dest, const CElemType* src);

// 元素打印
Result PrintElement(const CElemType* e);

顺序表基础知识

顺序表基本定义

顺序表在物理结构上的表现就是一个大数组,其逻辑结构可以由物理结构来体现,所以无需用额外的代码来体现逻辑结构。
故而顺序表可以看作是一个大数组加上一些额外的信息,再加上一些方法。

定义一个顺序表结构

#define MAXSIZE 100 // 大数组的数目大小
typedef struct CSqList_t
{
    CElemType data[MAXSIZE]; // 大数组
    int length; // 额外的信息, 用于存储当前数组有效元素的数目
} CSqList;

顺序表的方法

获取某个位置的元素的值

/* 初始条件:顺序线性表L已存在,1≤pos≤ListLength(L) */
/* 操作结果:用e返回L中第pos个数据元素的值,注意pos是指位置,第1个位置的数组是从0开始 */
Result SeqListGetElem(const CSqList* list, int pos, CElemType* elem)
{
	// 先对入参进行判断
    if (NULL == list || NULL == elem)
    {
        printf("in SeqListGetElem:: in parameter err.\n");
        return RES_PARA_ERROR;
    }
    // 判断顺序表是否为空
    if (0 == list->length)
    {
        printf("in SeqListGetElem:: list is empty.\n");
        return RES_LIST_EMPTY_ERROR;
    }
    // 判断位置的是否越界
    if (pos < 1 || pos > list->length)
    {
        printf("in SeqListGetElem:: range of sqlist err.\n");
        return RES_RANGE_ERROR;
    }
    // 使用ElementAssignment函数取出位置为pos的元素值赋予e
    // 由于顺序表可以看作是一个大数组, 所以时间复杂度为 O(1)
    return ElementAssignment(elem, &list->data[pos - 1]);
}

C语言版

CType.h

#ifndef _C_TYPES_H 
#define _C_TYPES_H 1 
#ifdef __cplusplus
extern "C" {
#endif

/*
#define OK      1
#define ERROR   0
#define TRUE    1
#define FALSE   0
*/

enum Result_t
{
	RES_OK = 0,
	RES_BOOL_TRUE,
	RES_BOOL_FALSE,
	RES_CMP_EQUAL,
	RES_CMP_GREATER,
	RES_CMP_LESS,
	RES_BASE_ERROR,
	RES_PARA_ERROR,
	RES_LIST_EMPTY_ERROR,
	RES_LIST_FULL_ERROR,
	RES_RANGE_ERROR
};
typedef enum Result_t Result;

#define ELEM_IS_INT 0
#if !ELEM_IS_INT
struct CElemType_t
{
	int index;
	char message[64];
};
typedef struct CElemType_t CElemType;
#else
typedef int ElemType;
#endif
#define EXAMPLE_ELEM_ARRAY_LENGTH 100
extern CElemType EXAMPLE_ELEM_ARRAY[EXAMPLE_ELEM_ARRAY_LENGTH];

/**
 * 元素比较:
 * ret:
 * e1 >  e2: 1
 * e1 == e2: 0
 * e1 <  e2: -1
 * 入参错误: -2
**/
Result ElementCompare(const CElemType *e1, const CElemType *e2);

// 元素赋值
Result ElementAssignment(CElemType *dest, const CElemType *src);

// 元素打印
Result PrintElement(const CElemType *e);

#ifdef __cplusplus
}
#endif
#endif

CType.c

#include <stdio.h>
#include <string.h>

#include "CTypes.h"

CElemType EXAMPLE_ELEM_ARRAY[EXAMPLE_ELEM_ARRAY_LENGTH] = {
#if ELEM_IS_INT	
    0,
	1, 
	2,
	3,
	4,
	5,
	6,
	7,
	8,
	9,
	10,
	11,
	12,
	13,
	14,
	15,
	16,
    17,
    18,
    19,
    20
#else
    {0,  "00"},
    {1,  "AA"},
    {2,  "BB"},
    {3,  "CC"},
    {4,  "DD"},
    {5,  "EE"},
    {6,  "FF"},
    {7,  "GG"},
    {8,  "HH"},
    {9,  "II"},
    {10, "JJ"},
    {11, "KK"},
    {12, "LL"},
    {13, "MM"},
    {14, "NN"},
    {15, "OO"},
    {16, "PP"},
    {17, "QQ"},
    {18, "RR"},
    {19, "SS"},
    {20, "TT"}
#endif
};


// 元素赋值
Result ElementAssignment(CElemType *dest, const CElemType *src)
{
    if (NULL == dest || NULL == src)
    {
        printf("in ElementAssignment:: in parameter err.\n");
        return RES_PARA_ERROR;
    }
#if ELEM_IS_INT	
    *dest = *src;
#else
    dest->index = src->index;
    strcpy(dest->message, src->message);
#endif
    return RES_OK;
}

// 元素打印
Result PrintElement(const CElemType *e)
{
    if (NULL == e)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return RES_PARA_ERROR;
    }
#if ELEM_IS_INT	
    printf("%d ", *e);
#else
    printf("%03d\t%s\n", e->index, e->message);
#endif
    return RES_OK;
}

Result ElementCompare(const CElemType *e1, const CElemType *e2)
{
    if (NULL == e1 || NULL == e2)
    {
        printf("in ElementAssignment:: in parameter err.\n");
        return RES_PARA_ERROR;
    }
#if ELEM_IS_INT	
    if (*e1 > *e2)
    {
        return RES_CMP_GREATER;
    }
    else if (*e1 < *e2)
    {
        return RES_CMP_LESS;
    }
#else
    if (e1->index > e2->index)
    {
        return RES_CMP_GREATER;
    }
    else if (e1->index < e2->index)
    {
        return RES_CMP_LESS;
    }
    else
    {
        int ret = strcmp(e1->message, e2->message);
        if (ret > 0)
        {
            return RES_CMP_GREATER;
        }
        else if (ret < 0)
        {
            return RES_CMP_LESS;
        }
    }
#endif
    return RES_CMP_EQUAL;
}

CSeqList.h

#ifndef _C_SeqList_H
#define _C_SeqList_H 1
#ifdef __cplusplus
extern "C" {
#endif

#include "CTypes.h"

#define __TEST_C_SEQ_LIST__ 1 // 测试样例
// gcc ./CSeqList.c ./CTypes.c -I ./ -o c_seqlist_test -Wall

#define MAXSIZE 100

typedef struct CSqList_t 
{
    CElemType data[MAXSIZE];
    int length;
} CSqList;

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
Result SeqListGetElem(const CSqList *list, int index, CElemType *elem);

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Result SeqListInsert(CSqList *list, int index, const CElemType *elem);

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Result SeqListDelete(CSqList *list, int index, CElemType *elem);

/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Result SeqListIsEmpty(const CSqList *list);

/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Result ClearSeqList(CSqList *list);

/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int SeqListLength(const CSqList *list);

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足相同关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int SeqListLocateElem(const CSqList *list, const CElemType* e);

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Result SeqListTraverse(const CSqList *list);

/*将所有的在线性表Lb中但不在La中的数据元素插入到La中*/
Result UnionSeqList(CSqList *La, const CSqList *Lb);

#ifdef __cplusplus
}
#endif
#endif

CSeqList.c

#include <stdio.h>
#include <string.h>

#include "CSeqList.h"

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:用e返回L中第i个数据元素的值,注意i是指位置,第1个位置的数组是从0开始 */
Result SeqListGetElem(const CSqList *list, int index, CElemType *elem)
{
    if (NULL == list || NULL == elem)
    {
        printf("in SeqListGetElem:: in parameter err.\n");
        return RES_PARA_ERROR;
    }
    if (0 == list->length)
    {
        printf("in SeqListGetElem:: list is empty.\n");
        return RES_LIST_EMPTY_ERROR;
    }
    if (index < 1 || index > list->length)
    {
        printf("in SeqListGetElem:: range of sqlist err.\n");
        return RES_RANGE_ERROR;
    }
    return ElementAssignment(elem, &list->data[index-1]);
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L), */
/* 操作结果:在L中第i个位置之前插入新的数据元素e,L的长度加1 */
Result SeqListInsert(CSqList *list, int index, const CElemType *elem)
{
    int i = 0;
    Result ret;

    if (NULL == list || NULL == elem)
    {
        printf("in SeqListInsert:: in parameter err.\n");
        return RES_PARA_ERROR;
    }

    if (MAXSIZE == list->length)
    {
        printf("in SeqListInsert:: List full.\n");
        return RES_LIST_FULL_ERROR;
    }
    if (index < 1 || index > list->length + 1)
    {
        printf("in SeqListInsert:: index is illegal, err.\n");
        return RES_RANGE_ERROR;
    }

    for (i = list->length-1; i >= index-1; i--)
    {
        ret = ElementAssignment(&list->data[i+1], &list->data[i]);
        if (ret != RES_OK)
        {
            printf("in SeqListInsert:: ElementAssignment() error.\n");
            return ret;
        }
    }

    ret = ElementAssignment(&list->data[index-1], elem);
    if (ret != RES_OK)
    {
        printf("in SeqListInsert:: ElementAssignment() error.\n");
        return ret;
    }
    list->length++;
    return RES_OK;
}

/* 初始条件:顺序线性表L已存在,1≤i≤ListLength(L) */
/* 操作结果:删除L的第i个数据元素,并用e返回其值,L的长度减1 */
Result SeqListDelete(CSqList *list, int index, CElemType *elem)
{
    int i = 0;
    Result ret;

    if (NULL == list)
    {
        printf("in SeqListDelete:: in parameter err.\n");
        return RES_PARA_ERROR;
    }

    if (0 == list->length)
    {
        printf("in SeqListDelete:: list is empty.\n");
        return RES_LIST_EMPTY_ERROR;
    }

    if (index < 1 || index > list->length)
    {
        printf("in SeqListDelete:: index is illegal.\n");
        return RES_PARA_ERROR;
    }

    if (elem != NULL)
    {
        ret = ElementAssignment(elem, &list->data[index-1]);
        if (ret != RES_OK)
        {
            printf("in SeqListDelete:: ElementAssignment() failed.\n");
            return ret;
        }
    }

    for (i = index; i < list->length; i++)
    {
        ret = ElementAssignment(&list->data[i-1], &list->data[i]);
        if (ret != RES_OK)
        {
            printf("in SeqListDelete:: ElementAssignment() failed.\n");
            return ret;
        }
    }
    list->length--;
    return RES_OK;
}

/* 创建顺序线性表 */
Result InitSeqList(CSqList* list)
{
	if (NULL == list)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return RES_PARA_ERROR;
    }
	memset(list, 0, sizeof(CSqList));
	list->length = 0;
	return RES_OK;
}

/* 初始条件:顺序线性表L已存在。操作结果:若L为空表,则返回TRUE,否则返回FALSE */
Result SeqListIsEmpty(const CSqList *list)
{
    if (NULL == list)
    {
        printf("in SeqListIsEmpty:: in parameter err.\n");
        return RES_PARA_ERROR;
    }
    return ((list->length > 0) ? RES_BOOL_FALSE : RES_BOOL_TRUE);
}

/* 初始条件:顺序线性表L已存在。操作结果:将L重置为空表 */
Result ClearSeqList(CSqList *list)
{
    if (NULL == list)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return RES_PARA_ERROR;
    }
    list->length = 0;
    return RES_OK;
}

/* 初始条件:顺序线性表L已存在。操作结果:返回L中数据元素个数 */
int SeqListLength(const CSqList *list)
{
    if (NULL == list)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return -1;
    }
    return list->length;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */
/* 若这样的数据元素不存在,则返回值为0 */
int SeqListLocateElem(const CSqList *list, const CElemType* e)
{
    int i = 0;
    if (NULL == list || NULL == e)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return 0;
    }
    
    for (i = 0; i < list->length; i++)
    {
        if (ElementCompare(&list->data[i], e) == RES_CMP_EQUAL)
        {
            return i+1;
        }
    }
    return 0;
}

/* 初始条件:顺序线性表L已存在 */
/* 操作结果:依次对L的每个数据元素输出 */
Result SeqListTraverse(const CSqList *list)
{
    int i = 0;
    Result ret;
    if (NULL == list)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return RES_PARA_ERROR;
    }
    for (i = 0; i < list->length; i++)
    {
        ret = PrintElement(&list->data[i]);
        if (ret != RES_OK)
        {
            printf("in SeqListTraverse:: PrintElement() failed.\n");
            return ret;
        }
    }
    printf("\n");
    return RES_OK;
}

/*将所有的在线性表Lb中但不在La中的数据元素插入到La中*/
Result UnionSeqList(CSqList *La, const CSqList *Lb)
{
    if (NULL == La || NULL == Lb)
    {
        printf("in %s:: in parameter err.\n", __func__);
        return RES_PARA_ERROR;
    }
	int i = 0;
	CElemType e;
	Result ret;
	int Lb_len = 0;

	Lb_len = SeqListLength(Lb);

	for (i = 1; i <= Lb_len; i++)
	{
		ret = SeqListGetElem(Lb, i, &e);
        if (ret != RES_OK)
		{
			printf("in UnionSeqList:: SeqListGetElem() failed.\n");
			return ret;
		}
		if (SeqListLocateElem(La, &e) != 0)
		{
			continue;
		}
		ret = SeqListInsert(La, SeqListLength(La)+1, &e);
		if (ret != RES_OK)
		{
			printf("in UnionSeqList:: SeqListInsert() failed.\n");
			return ret;
		}
	}
	return RES_OK;
}

#if __TEST_C_SEQ_LIST__

#include <stdlib.h>

void JudgeRes(Result res, int line)
{
	if (res >= RES_BASE_ERROR)
	{
		printf("exit() in [%d].\n", line);
		exit(1);
	}
}

int main()
{
	int i, j;

	CSqList L;
	CSqList Lb;

	CElemType e;
	Result ret;

	ret = InitSeqList(&L);
	JudgeRes(ret, __LINE__);
	printf("初始化L后: SeqListLength(&L) = [%d].\n", SeqListLength(&L));


	for (i = 1; i <= 5; i++)
	{
        ret = SeqListInsert(&L, 1, &EXAMPLE_ELEM_ARRAY[i]);
		JudgeRes(ret, __LINE__);
	}
	printf("在L的表头依次插入 EXAMPLE_ELEM_ARRAY[1]~EXAMPLE_ELEM_ARRAY[5] 后: L.data = \n");
	ret = SeqListTraverse(&L);
	JudgeRes(ret, __LINE__);
	printf("SeqListLength(&L) = [%d].\n", SeqListLength(&L));


	ret = SeqListIsEmpty(&L);
	JudgeRes(ret, __LINE__);
	if (RES_BOOL_TRUE == ret)
	{
		printf("L is empty.\n");
	}
	else if (RES_BOOL_FALSE == ret)
	{
		printf("L is not empty.\n");
	}

	ret = ClearSeqList(&L);
	JudgeRes(ret, __LINE__);
	printf("ClearSeqList()后: SeqListLength(&L) = [%d].\n", SeqListLength(&L));
	ret = SeqListIsEmpty(&L);
	JudgeRes(ret, __LINE__);
	if (RES_BOOL_TRUE == ret)
	{
		printf("L is empty.\n");
	}
	else if (RES_BOOL_FALSE == ret)
	{
		printf("L is not empty.\n");
	}


	for (i = 1; i <= 10; i++)
	{
		ret = SeqListInsert(&L, SeqListLength(&L)+1, &EXAMPLE_ELEM_ARRAY[i]);
		JudgeRes(ret, __LINE__);
	}
	printf("在L的表尾依次插入 EXAMPLE_ELEM_ARRAY[1]~EXAMPLE_ELEM_ARRAY[10] 后: L.data = \n");
    ret = SeqListTraverse(&L); 
	JudgeRes(ret, __LINE__);
	printf("SeqListLength(&L) = [%d].\n", SeqListLength(&L));


	ret = SeqListInsert(&L, 1, &EXAMPLE_ELEM_ARRAY[0]);
	JudgeRes(ret, __LINE__);
	printf("在L的表头插入 EXAMPLE_ELEM_ARRAY[0] 后: L.data = \n");
	ret = SeqListTraverse(&L); 
	JudgeRes(ret, __LINE__);
	printf("SeqListLength(&L) = [%d].\n", SeqListLength(&L));


	ret = SeqListGetElem(&L, 5, &e);
	JudgeRes(ret, __LINE__);
	printf("第5个元素的值为:\n");
	PrintElement(&e);
    printf("\n");

	for (j = 3; j <= 4; j++)
    {
		i = SeqListLocateElem(&L, &EXAMPLE_ELEM_ARRAY[j]);
		if (i != 0)
		{
			printf("第[%d]个元素的值为:\n", i);
			PrintElement(&EXAMPLE_ELEM_ARRAY[j]);
			printf("\n");
		}
		else
		{
			printf("没有值为:\n");
			PrintElement(&EXAMPLE_ELEM_ARRAY[j]);
			printf("\n的元素.\n");

		}
    }

	i = SeqListLength(&L);
	for (j = i+1; j>=i; j--)
    {
            ret = SeqListDelete(&L, j, &e); /* 删除第j个数据 */
            if (ret != RES_OK)
			{
                printf("删除第[%d]个数据失败\n",j);
			}
			else
			{
                printf("删除第%d个的元素值为:\n", j);
				PrintElement(&e);
				printf("\n");
			}
    }
    printf("依次输出L的元素:\n");
    ret = SeqListTraverse(&L); 
	JudgeRes(ret, __LINE__);


	j = 5;
	ret = SeqListDelete(&L, j, &e); /* 删除第j个数据 */
	if (ret != RES_OK)
	{
		printf("删除第[%d]个数据失败\n", j);
	}
	else
	{
		printf("删除第%d个的元素值为:\n",  j);
		PrintElement(&e);
		printf("\n");
	}

	printf("依次输出L的元素:\n");
    ret = SeqListTraverse(&L); 
	JudgeRes(ret, __LINE__);

	ret = InitSeqList(&Lb);
	JudgeRes(ret, __LINE__);
	for (i = 6; i <= 15; i++)
	{
		ret = SeqListInsert(&Lb, 1, &EXAMPLE_ELEM_ARRAY[i]);
		JudgeRes(ret, __LINE__);
	}

	ret = UnionSeqList(&L, &Lb);
	JudgeRes(ret, __LINE__);

	printf("依次输出L的元素:\n");
    ret = SeqListTraverse(&L); 
	JudgeRes(ret, __LINE__);

	return 0;
}

#endif

C++ 版本

Type.hpp

#ifndef _TYPE_H
#define _TYPE_H 1

#include <cstring>
#include <iostream>

enum class Result : unsigned 
{
    RES_OK = 0,
    RES_BASE_ERROR,
	RES_INIT_FAIL,
	RES_PARA_ERROR,
	RES_LIST_EMPTY_ERROR,
	RES_LIST_FULL_ERROR,
	RES_RANGE_ERROR,
	RES_MALLOC_FAIL
};

class ElemType
{
private:
	int m_index;
	char m_message[64];

public:
	friend std::ostream& operator<<(std::ostream& stream, const ElemType& e);
public:
	ElemType() noexcept
		: m_index(0)
	{
		std::memset(m_message, 0, sizeof(m_message));
	}
	ElemType(const ElemType& elem) noexcept
		: m_index(elem.m_index)
	{
		std::strcpy(m_message, elem.m_message);
	}
	ElemType(int index, const char *message) noexcept
		: m_index(index)
	{
		std::strncpy(m_message, message, sizeof(m_message));
	}
	~ElemType() = default;
	bool operator<(const ElemType& other) noexcept
	{
		if (this->m_index < other.m_index)
		{
			return true;
		}	
		if (this->m_index == other.m_index && std::strcmp(this->m_message, other.m_message) < 0)
		{
			return true;
		}
		return false;
	}
	bool operator==(const ElemType& other) noexcept
	{
		if (this->m_index == other.m_index && std::strcmp(this->m_message, other.m_message) == 0)
		{
			return true;
		}
		return false;
	}
	bool operator>(const ElemType& other) noexcept
	{
		if (*this < other)
		{
			return false;
		}
		else if (*this == other)
		{
			return false;
		}
		return true;
	}

	ElemType& operator=(const ElemType& other) noexcept
	{
		if (this != &other)
		{
			m_index = other.m_index;
			std::memset(m_message, 0, sizeof(m_message));
			std::strcpy(m_message, other.m_message);
		}
		return *this;
	}
};

std::ostream& operator<<(std::ostream& stream, const ElemType& e)
{
	stream << e.m_index << '\t' << e.m_message << '\n';
	return stream;
}

#endif

SeqList.cpp

#ifndef _SEQLIST_H
#define _SEQLIST_H 1

#include <string>
#include <iostream>
#include <exception>
#include <functional>

#include "Type.hpp"

#define __TEST_SEQLIST__ 1

template <typename T> class SeqList
{
private:
    T* m_data;
    int m_length;
	const int m_max_nums;

public:
    SeqList(int max_nums, Result& res) noexcept
		: m_data(nullptr), m_length(0), m_max_nums(max_nums)
	{
		res = Result::RES_OK;
		try 
		{
            m_data = new T[m_max_nums];
        }
        catch (const std::exception& e)
        {
            std::cout << "in SeqList:: new failed, exception = " << e.what() << std::endl;
            res = Result::RES_INIT_FAIL;
        }
	}
	SeqList(const SeqList& L)
		: m_data(nullptr), m_length(0), m_max_nums(L.m_max_nums)
	{
		Result res;
		std::string exception_message;
		try 
		{
            m_data = new T[m_max_nums];
			for (int i = 0; i < L.length(); i++)
			{
				res = this->insert(i, L[i]);
				if (res != Result::RES_OK)
				{
					exception_message = std::string("in SeqList:: this->insert() failed.");
					break;
				}
			}
        }
        catch (const std::exception& e)
        {
            res = Result::RES_INIT_FAIL;
			exception_message = std::string("in SeqList:: new failed, exception = ") + std::string(e.what());
        }

		if (res != Result::RES_OK)
		{
			throw std::out_of_range(exception_message);
		}
	}
	SeqList& operator=(const SeqList& L)
	{
		if (this == &L)
		{
			return *this;
		}

		if (m_data != nullptr)
        {
            delete[] m_data;
            m_data = nullptr;
        }
        m_length = 0;
		{
			int& ref_m_max_nums = const_cast<int&>(this->m_max_nums);
			ref_m_max_nums = L.m_max_nums;
		}

		Result res;
		std::string exception_message;
		try 
		{
            m_data = new T[m_max_nums];
			for (int i = 0; i < L.length(); i++)
			{
				res = this->insert(i, L[i]);
				if (res != Result::RES_OK)
				{
					exception_message = std::string("in SeqList:: this->insert() failed.");
					break;
				}
			}
        }
        catch (const std::exception& e)
        {
            res = Result::RES_INIT_FAIL;
			exception_message = std::string("in SeqList:: new failed, exception = ") + std::string(e.what());
        }

		if (res != Result::RES_OK)
		{
			throw std::out_of_range(exception_message);
		}
	}
	SeqList(SeqList&& L) noexcept
		: m_data(L.m_data), m_length(L.m_length), m_max_nums(L.m_max_nums)
	{
		L.m_data = nullptr;
		L.m_length = 0;
	}
	SeqList& operator=(SeqList&& L) noexcept
	{
		if (this == &L)
		{
			return *this;
		}

		if (m_data != nullptr)
        {
            delete[] m_data;
            m_data = nullptr;
        }
		m_data = L.m_data;
		L.m_data = nullptr;
        m_length = L.m_length;
		L.m_length = 0;	
		{
			int& ref_m_max_nums = const_cast<int&>(this->m_max_nums);
			ref_m_max_nums = L.m_max_nums;
		}
	}
	SeqList(const SeqList& L, Result& res) noexcept
		: m_data(nullptr), m_length(0), m_max_nums(L.m_max_nums)
	{
		res = Result::RES_OK;
		try 
		{
            m_data = new T[m_max_nums];
			for (int i = 0; i < L.length(); i++)
			{
				res = this->insert(i, L[i]);
				if (res != Result::RES_OK)
				{
					std::cout << "in SeqList:: this->insert() failed.\n";
					break;
				}
			}
        }
        catch (const std::exception& e)
        {
            std::cout << "in SeqList:: new failed, exception = " << e.what() << std::endl;
            res = Result::RES_INIT_FAIL;
        }
	}
    ~SeqList() noexcept
    {
        if (m_data != nullptr)
        {
            delete[] m_data;
            m_data = nullptr;
        }
        m_length = 0;
    }

    T& operator[] (int index)
    {
		const char *exception_message = nullptr;
        if (nullptr == m_data)
        {
			exception_message = "in SeqList::operator[]:: list not init()";
        }
        else if (0 == m_length)
        {
            exception_message = "in SeqList::operator[]:: list empty";
        }
		else if (index < 1 || index > m_length)
		{
			exception_message = "in SeqList::operator[]:: index illegal";
		}

		if (exception_message != nullptr)
		{
			std::cout << exception_message << std::endl;
            throw std::out_of_range(exception_message);
		}
		return m_data[index-1];
    }

	const T& operator[] (int index) const
    {
		const char *exception_message = nullptr;
        if (nullptr == m_data)
        {
			exception_message = "in SeqList::operator[]:: list not init()";
        }
        else if (0 == m_length)
        {
            exception_message = "in SeqList::operator[]:: list empty";
        }
		else if (index < 1 || index > m_length)
		{
			exception_message = "in SeqList::operator[]:: index illegal";
		}

		if (exception_message != nullptr)
		{
			std::cout << exception_message << std::endl;
            throw std::out_of_range(exception_message);
		}
		return m_data[index-1];
    }

	Result insert(int index, const T &e) noexcept
	{
		if (nullptr == m_data)
		{
			std::cout << "in SeqList::insert:: list is not init.\n";
			return Result::RES_LIST_EMPTY_ERROR;
		}

		if (m_max_nums == m_length)
		{
			std::cout << "in SeqList::insert:: list full.\n";
			return Result::RES_LIST_FULL_ERROR;
		}

		if (index < 1 || index > m_length + 1)
		{
			std::cout << "in SeqList::insert:: index illegal.\n";
			return Result::RES_PARA_ERROR;
		}
		for (int i = m_length-1; i >= index-1; i--)
		{
			m_data[i+1] = std::move(m_data[i]);
		}
		m_data[index-1] = e;
		m_length++;
		return Result::RES_OK;
	}

	Result del(int index, T *del_elem = nullptr) noexcept
	{
		if (nullptr == m_data)
		{
			std::cout << "in SeqList::del:: list is not init.\n";
			return Result::RES_LIST_EMPTY_ERROR;
		}

		if (0 == m_length)
		{
			std::cout << "in SeqList::del:: list is empty.\n";
			return Result::RES_LIST_EMPTY_ERROR;
		}

		if (index < 1 || index > m_length)
		{
			std::cout << "in SeqList::del:: index illegal.\n";
			return Result::RES_PARA_ERROR;
		}

		if (del_elem != nullptr)
		{
			*del_elem = std::move(m_data[index-1]);
		}

		for (int i = index; i < m_length; i++)
		{
			m_data[i-1] = std::move(m_data[i]);
		}
		m_length--;
		return Result::RES_OK;
	}

	bool is_empty() const noexcept
	{
		return (m_length == 0 ? true : false);
	}

	Result clear() noexcept
	{
		if (nullptr == m_data)
		{
			std::cout << "in SeqList::clear:: list is not init.\n";
			return Result::RES_LIST_EMPTY_ERROR;
		}
		m_length = 0;
		return Result::RES_OK;
	}

	int length() const noexcept
	{
		return m_length;
	}

	/**
	 * 初始条件:顺序线性表L已存在
	 * 操作结果:返回L中第1个与e满足关系的数据元素的位序。
	 * 若这样的数据元素不存在,则返回值为0
	**/
	int locate_elem(const T& e)
	{
		if (nullptr == m_data)
		{
			std::cout << "in SeqList::locate_elem:: list is not init.\n";
			return 0;
		}
		for (int i = 0; i < m_length; i++)
		{
			if (m_data[i] == e)
			{
				return i+1;
			}
		}
		return 0;
	}

	void traverse(std::ostream& out_stream = std::cout) noexcept
	{
		for (int i = 0; i < m_length; i++)
		{
			out_stream << m_data[i];
		}
		out_stream << '\n';
	}

	SeqList& operator+=(const SeqList& other_list)
	{
		const char *exception_message = nullptr;
		if (nullptr == m_data || nullptr == other_list.m_data)
		{
			exception_message = "in SeqList::locate_elem:: list is not init.";
			std::cout << exception_message << std::endl;
			throw std::out_of_range(exception_message);
		}

		T e;
		for (int i = 1; i <= other_list.length(); i++)
		{
			e = other_list[i];
			if (this->locate_elem(e) != 0)
			{
				continue;
			}
			if (this->insert(this->length()+1, e) != Result::RES_OK)
			{
				exception_message = "in SeqList::operator+=:: this->insert() failed.";
				std::cout << exception_message << std::endl;
				throw std::out_of_range(exception_message);
			}
		}
		return *this;;
	}
};

#endif

cplusplus_test.cpp

#include <iostream>

#include "SeqList.hpp"
// g++ -std=c++23 -Wall cplusplus_test.cpp -I ./ -o cplusplus_test

static void JudgeRes(const Result& res, int line)
{
	if (res >= Result::RES_BASE_ERROR)
	{
		printf("exit() in [%d].\n", line);
		exit(1);
	}
}

ElemType EXAMPLE_ELEM_ARRAY[] = {
    ElemType(0,  "00"),
    ElemType(1,  "AA"),
    ElemType(2,  "BB"),
    ElemType(3,  "CC"),
    ElemType(4,  "DD"),
    ElemType(5,  "EE"),
    ElemType(6,  "FF"),
    ElemType(7,  "GG"),
    ElemType(8,  "HH"),
    ElemType(9,  "II"),
    ElemType(10, "JJ"),
    ElemType(11, "KK"),
    ElemType(12, "LL"),
    ElemType(13, "MM"),
    ElemType(14, "NN"),
    ElemType(15, "OO"),
    ElemType(16, "PP"),
    ElemType(17, "QQ"),
    ElemType(18, "RR"),
    ElemType(19, "SS"),
    ElemType(20, "TT")
};

int main()
{
    int i = 0;
    Result ret;
    ElemType elem;

#if __TEST_SEQLIST__
    SeqList<ElemType> L(100, ret);
    JudgeRes(ret, __LINE__);
    SeqList<ElemType> Lb(100, ret);
    JudgeRes(ret, __LINE__);
    std::cout << "初始化L后: L.length() = " << L.length() << std::endl;

    for (i = 1; i <= 5; i++)
    {
        ret = L.insert(1, EXAMPLE_ELEM_ARRAY[i]);
        JudgeRes(ret, __LINE__);
    }
    std::cout << "在L的表头依次插入 EXAMPLE_ELEM_ARRAY[1]~EXAMPLE_ELEM_ARRAY[5] 后: L.data = \n";
    L.traverse();
    std::cout << "L.length() = " << L.length() << std::endl;

    if (true == L.is_empty())
    {
        std::cout << "L is empty.\n";
    }
    else
    {
        std::cout << "L is not empty.\n";
    }

    ret = L.clear();
    JudgeRes(ret, __LINE__);
    std::cout << "L.clear()后: L.length() = " << L.length() << std::endl;
    if (true == L.is_empty())
    {
        std::cout << "L is empty.\n";
    }
    else
    {
        std::cout << "L is not empty.\n";
    }

    for (i = 1; i <= 10; i++)
    {
        ret = L.insert(L.length()+1, EXAMPLE_ELEM_ARRAY[i]);
        JudgeRes(ret, __LINE__);
    }
    std::cout << "在L的表尾依次插入 EXAMPLE_ELEM_ARRAY[1]~EXAMPLE_ELEM_ARRAY[10] 后: L.data = \n";
    L.traverse();
    std::cout << "L.length() = " << L.length() << std::endl;


    ret = L.insert(1, EXAMPLE_ELEM_ARRAY[0]);
    JudgeRes(ret, __LINE__);
    std::cout << "在L的表头插入 EXAMPLE_ELEM_ARRAY[0] 后: L.data = \n";
    L.traverse();
    JudgeRes(ret, __LINE__);
    std::cout << "L.length() = " << L.length() << std::endl;

    try {
        elem = L[5];
    }
    catch (const std::exception& e)
    {
        std::cout << "Get Elem failed.\n";
        exit(-1);
    }
    std::cout << "第5个元素的值为:\n";
    std::cout << elem << std::endl;

    for (int j = 3; j <= 4; j++)
    {
        i = L.locate_elem(EXAMPLE_ELEM_ARRAY[j]);
        if (i != 0)
        {
            std::cout << "第[" << i << "]个元素的值为:\n";
			std::cout << EXAMPLE_ELEM_ARRAY[j] << std::endl;
        }
        else
        {
            std::cout << "没有值为:\n";
			std::cout << EXAMPLE_ELEM_ARRAY[j] << "\n的元素.\n";
        }
    }

    i = L.length();
    for (int j = i+1; j >= i; j--)
    {
        ret = L.del(j, &elem);
        if (ret != Result::RES_OK)
        {
            std::cout << "删除第[" << j << "]个数据失败\n";
        }
        else
        {
            std::cout << "删除第[" << j << "]个的元素值为:\n" << elem << std::endl;
        }
    }
    std::cout << "依次输出L的元素:\n";
    L.traverse();

    i = 5;
    ret = L.del(i, &elem);
    if (ret != Result::RES_OK)
    {
        std::cout << "删除第[" << i << "]个数据失败\n";
    }
    else
    {
        std::cout << "删除第[" << i << "]个的元素值为:\n" << elem << std::endl;
    }

    std::cout << "依次输出L的元素:\n";
    L.traverse();

    for (i = 6; i <= 15; i++)
    {
        ret = Lb.insert(1, EXAMPLE_ELEM_ARRAY[i]);
        JudgeRes(ret, __LINE__);
    }

    L += Lb;

    std::cout << "依次输出L的元素:\n";
    L.traverse();
#endif

    return 0;
}
数据结构课程设计C/C++版--植物百科数据的管理与分析 阅读详情

相关推荐

顺序表的实现(C++)

数据结构中的顺序表的实现其中包括初始化、删除、插入。还有额外的翻转、合并。本人用DEVC++亲测可以运行

数据结构-线性表的顺序表基本操作代码实现(超级详细清晰 C++实现)

数据结构-线性表的顺序表基本操作代码实现(超级详细清晰 C++实现)

Jason_WSYCY的博客 4864

软件工程:数据字典

数据字典

永远怀着至诚之心拥抱世界 4275

顺序表(C++实现)

在f2函数中,我们可以使用lambda表达式或者std::bind将f1函数绑定到函数对象上,并将这个函数对象作为参数传递给for_each算法,从而实现在f2函数中调用f1函数。注意,在lambda表达式或者std::bind中,必须将当前对象的指针通过this传递进去,以确保能够调用类的成员函数。对于全局函数,因为它们不属于类的一部分,也没有成员变量可以被限制为只读,在全局函数中使用 const 关键字是无效的。

believeme464646的博客 2071

基于Python的闲鱼商品价格评估模型:爬虫+价格预测全实现

本文介绍了一个完整的全球气候数据抓取与分析流程,采用轻量化的技术栈(requests+pandas+matplotlib+folium),实现以下核心功能: 全球城市定向抓取:支持自定义城市列表,自动获取经纬度并抓取多源气候数据 双数据源互补:结合OpenWeatherMap API(实时数据)和Climate-Data.org(历史数据) 全维度覆盖:采集气温、降水、湿度等核心指标,并进行自动化清洗转换 丰富可视化:生成热力图、趋势图和统计图表,支持地理定位展示 灵活扩展:模块化设计便于新增城市或扩展数据

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 3047

QT邂逅豆包API:打造专属文章生成神器

通过本次探索,我们成功基于 QT 调用豆包 API 开发出了文章生成工具。从前期的准备工作,到核心代码的实现,再到功能的拓展与优化,每一步都凝聚着技术的魅力与挑战。我们学会了申请豆包 API 密钥,搭建 QT 开发环境,创建网络请求类来与豆包 API 进行交互,构建请求体并解析响应,还为工具添加了友好的界面交互,提升了性能。

大雨淅淅的博客 1973

顺序表(c++)

数据结构 顺序表

sin_0119的博客 2125

飞书多维表格省钱攻略:1个专业版账号,全员合规用、权限全掌控

像运动馆、 托管班、作业辅导、少儿美术、书法、口才班等等。对于大多数中小团队而言,飞书多维表格的核心需求是“协作高效、数据可控、成本可控”,而“1个专业版账号+多联系人”的模式,恰好完美契合这三点——既不用为不必要的席位付费,又能解锁全部专业功能,还能通过精细化权限管控保障数据安全。尤其是餐饮店、乒乓球训练馆这类个体经营或小型团队,人员分工清晰、权限需求明确,采用这种模式能最大化节省成本,同时提升管理效率。无需复杂的配置,无需额外的技术支持,5分钟就能搭建起全员协作的省钱体系。

涛涛讲AI 2217

C++实现顺序表的基本操作(含完整代码)

C++实现顺序表的基本操作(附完整代码) 1、顺序表的初始化 2、顺序表的长度 3、顺序表插入元素 4、删除顺序表元素 5、遍历顺序表 6、查找顺序表元素 完整代码: #include<iostream> using namespace std; #define MAXSIZE 100 typedef int elemtype; //elemtype 可以为任意类......

Henry的博客 3万+

QT5.14.2离线安装包保姆级教程:断网、选组件、避坑全记录

本文详细介绍了QT5.14.2离线安装包的完整流程,特别针对Windows平台开发者提供断网安装、组件选择及避坑指南。作为QT5系列中最后一个免费离线版本,5.14.2具有免注册、全组件离线安装等独特优势,是开源开发者的理想选择。文章涵盖从环境准备到安装后配置的全方位指导,帮助开发者高效完成安装并避免常见问题。

weixin_30924087的博客 578

汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案

汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案

m0_51658788的博客 3606

c++数据结构顺序表实现

c++数据结构中的方法通过面向对象的机制提高了程序的效率。

cangyue_a的博客 3428

最优化理论与自动驾驶(三):LQR原理、公式及代码演示

LQR 是基于线性系统和二次型代价函数的最优控制方法,在实际工程应用中,我们一般采用离散时间系统的LQR设计,其目标是通过设计反馈控制律,使系统在离散时间步长内稳定运行,最小化某个二次型代价函数。给定一个离散时间系统,其状态和控制输入通过以下方程表示:是时刻k的系统状态,是时刻k的控制输入,是状态转移矩阵,是输入矩阵。系统描述的物理意义:系统状态通过矩阵A演变到下一时刻,同时控制输入通过矩阵B影响系统的状态。

a8598671的博客 4595

数据结构C/C++代码实现 顺序表栈基本操作

顺序表栈基本操作的实现  源代码: #include&lt;stdio.h&gt; #include&lt;stdlib.h&gt; #include&lt;iostream&gt; using namespace std; #define MAXSIZE 100 //#define Status int #define OK 1 #define OVERFLOW -2 #define Fals...

你好,明天,,的博客 1045

YOLOv8优化:独家创新(SC_C_Detect)检测头结构创新,实现涨点 | 检测头新颖创新系列

独家创新(SC_C_Detect)检测头结构创新,适合科研创新度十足,强烈推荐

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 4873

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

数据结构基本操作(期末必备)(顺序表)

期末考点哦

脑子不好的小菜的博客 345

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

C++顺序表、链表的*插删查等*操作

顺序表 #include <iostream> #include <cstring> using std::cout; using std::endl; //定义顺序表模板类 template <typename Type> class Vector { private: int size, length; Type *data; public: Vector(int input_size) { size = input_size;

Nemoxy的博客 317

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【数据结构】线性表|顺序表|(全)测试代码|用C语言/C++实现动态及静态顺序表的定义、插入、删除、查找、打印输出等基本操作

1、静态顺序表的代码 #include<stdio.h> #define Maxsize 10 //定义最大长度 typedef struct { int data[Maxsize]; //定义一个长度为Maxsize的数组用来存放数据元素 int length; //顺序表的当前长度 }SqList; //基本操作——初始化一个顺序表 void InitList(SqList &L) { for (int i = 0;i < Maxsize;i++) {

dxy1128的博客 847

c/c++顺序表的定义与初始方法-----c/c++学习日志

c/c++顺序表 让我们先来看一张图片,帮助我们理解顺序表的结构 顺序表的存储方式和数组极为相似,相邻的两个存储元素地址也是相邻的。不过顺序表中间的存储元素不能有空值。下面看一下顺序表的定义与初始化,话不多说上代码`` ...

weixin_44340777的博客 531

学习C/C++ 第二十一天 数据结构——1.顺序表

学习这么多天了,还是有很多的收获,今天学习整个C/C++中最核心的内容:数据结构和算法 中的“数据结构”。 1.顺序表 是简单的一种线性结构,是连续存储方式,逻辑上相邻的数据在计算机内存储位置也是相邻的,可以快速定位几个元素,中间不允许有空值、插入。删除时需要移动大量元素。 a)用 elems 记录存储位置的基地址 b)分配一段连续的储存空间 size c)用 length 记录实际的元素个数...

w707577314的博客 189

手撕考研数据结构算法 100题(代码汇总篇)持续更新中~

数据结构是一门需要实践的学科,通过编写代码并进行调试,可以快速掌握相关知识。同时,它也是计算机和软件类考研无法绕过的重要内容。在这篇博客中,我将整理我在考研期间编写的数据结构代码,全部为可直接运行的C/C++代码,注释详细、风格统一。希望这些内容能帮助到备考的同学们!整个博客从线性表、树、图、查找排序四部分来列举考研数据结构中重要的内容。

weixin_62690215的博客 1036

【数据结构篇C++实现】- 线性表 - 顺序表和链表

线性表知识总结,一文搞懂什么是顺序表与链表,以及常见的操作

陈七的博客,学习知识分享,期待与大家的交流 4258

顺序表的插入、删除代码分析笔记

顺序表的插入、删除代码分析笔记

ul_traman的博客 1082

数据结构——线性表的顺序存储结构简单输出代码

在C/C++语言中,借助数组类型来实现顺序表,也就是说,用数组存放线性表的元素及其逻辑关系,数组的基本类型就是线性表中元素的的类型,数组大小(即数组上界-下界+1)要大于等于线性表的长度,否则该数组不能存放对应线性表的所有元素。所以当线性表长度小于数组大小时,该数组中会有一部分空闲空间。 注意:顺序表采用数组来实现,但不能将任何一个数组都当作是一个顺序表,二者的运算是不同的。 在定义一个线性表...

weixin_45310677的博客 2458

三元顺序表和行逻辑链接的顺序表

最近在回顾数据结构,第一次看矩阵压缩时,对三元顺序表和行逻辑连接顺序表的区别没想太明白,写了段代码梳理一下思路,顺带熟悉一下C/C++ #include<stdio.h> #include <stdlib.h> #define ArrSize 5 // 三元顺序表的元素结构 typedef struct { int i; // 在原表的第几行 int j; // 在原表的第几列 int data; // 存储的值 } Triple; // 三元顺序表结构

ma5074的博客 949

数据结构——顺序表的动态分配的创建及其添加、删除、查找等操作

//顺序表的动态分配的创建及其添加、删除、查找等操作 #include<stdio.h> #include<stdlib.h> #define InitSize 10 //表长度初始定义 typedef struct { int *data; //指示动态分配数组的指针(指向第一个元素) int MaxSize,length; //数组的最大容量和当前个数 }...

Prescu的博客 786
上一篇: [C++]利用可变模板将不定入参连接为字符串返回
下一篇: [Rust] Linux系统安装rust
scau_coderlin
博客等级 码龄3年 10粉丝 10原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值