【数据结构】—— 动态增长的顺序表相关接口实现

news/2024/5/20 9:06:54 标签: 数据结构, 顺序表, 动态增长

线性表的顺序存储

  • 线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素,使得线性表在逻辑结构上相邻的元素存储在连续的物理存储单元中,即:通过数据元素物理存储的连续性来反应元素之间逻辑上的相邻关系。采用顺序存储结构存储的线性表通常简称为顺序表

顺序存储的线性表的特点:

  • 线性表的逻辑顺序与物理顺序一致;
  • 数据元素之间的关系是以元素在计算机内“物理位置相邻”来体现。
  • 顺序存储支持随机访问,可通过下标进行访问
  • 顺序表头插头删效率低,时间复杂度为O(N)

顺序表在内存中的存储

<a class=顺序表在内存中的存储" />

顺序表源码

公共头文件common.h

#define _CRT_SECURE_NO_WARNINGS
#ifndef __SEQLIST_H__
#define __SEQLIST_H__


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

#endif //__SEQLIST_H__

顺序表头文件SeqList .h相关接口介绍

#include"common.h"
typedef int SLDataType;
// 顺序表的动态存储 
typedef struct SeqList
{
	SLDataType* array; // 指向动态开辟的数组 
	size_t _size; // 有效数据个数 
	size_t _capicity; // 容量空间的大小 
}SeqList;



 基本增删查改接口 
void SeqListInit(SeqList* psl, size_t capacity);//顺序表的初始化
void SeqListDestory(SeqList* psl);//销毁顺序表
//
void CheckCapacity(SeqList* psl);//增容
void SeqListPushBack(SeqList* psl, SLDataType x);//尾插
void SeqListPopBack(SeqList* psl);//尾删
void SeqListPushFront(SeqList* psl, SLDataType x);//头插
void SeqListPopFront(SeqList* psl);//头删
//
int SeqListFind(SeqList* psl, SLDataType x);//查找顺序表中的某个元素
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);//在pos位置处插入一个元素
void SeqListErase(SeqList* psl, size_t pos);//删除pos处的元素
void SeqListRemove(SeqList* psl, SLDataType x);//删除值为x的元素
void SeqListModify(SeqList* psl, size_t pos, SLDataType x);//将pos处的元素的值修改为x
void SeqListPrint(SeqList* psl);//打印顺序表中的元素
void SeqListBubbleSort(SeqList* psl);//通过冒泡排序对顺序表的元素进行排序
int  SeqListBinaryFind(SeqList* psl, SLDataType x);//二分查找一个元素的位置
void SeqListRmoveAll(SeqList* psl,SLDataType x);//清空顺序表

//
void SeqListtest1();//测试顺序表的相关接口

顺序表接口实现文件SeqList.c

#include"SeqList.h"

//顺序表的初始化
void SeqListInit(SeqList* psl, size_t capacity)
{
	assert(psl != NULL);
	//给顺序表分配初始空间
	psl->array = (SLDataType*)malloc(capacity*sizeof(SLDataType));
	psl->_size = 0;
	psl->_capicity = capacity;
}

 //销毁一个顺序表
void SeqListDestory(SeqList* psl)
{
	assert(psl != NULL);
	if (psl->array)//判断是否有为顺序表开辟空间,有则释放
	{
		free(psl->array);
		psl->array = NULL;
		psl->_size = 0;
		psl->_capicity = 0;
	}
	
}

 //打印一个顺序表
void SeqListPrint(SeqList* psl)
{
	assert(psl);
	if (psl->array != NULL)
	{//打印顺序表的元素,通过下标访问
		for (size_t i = 0; i < psl->_size; i++)
		{
			printf("%d ", psl->array[i]);
		}
	}
	printf("\n");
}

// 检查是否需要增容
void CheckCapacity(SeqList* psl)
{
	
	assert(psl != NULL);

	if (psl->_size == psl->_capicity)//若是实际插入的数据个数与容量相等时,说明需要增容
	{
		psl->_capicity *= 2;//顺序表的容量以两倍的速度增长
		//为顺序表重新申请空间
		psl->array = (SLDataType*)realloc(psl->array, psl->_capicity*sizeof(SLDataType));
		assert(psl->array);//判断重新申请空间是否成功
	}
		
}

//在顺序表的尾插入一个元素,时间复杂度为O(1)
void SeqListPushBack(SeqList* psl, SLDataType x)
{
	//在顺序表尾上插入数据
	assert(psl);
	CheckCapacity(psl);
	psl->array[psl->_size] = x;
	psl->_size++;
}

//顺序表尾部删除一个元素,时间复杂度为O(1)
void SeqListPopBack(SeqList* psl)
{
	assert(psl);
	psl->array[psl->_size] = 0;//将最后一个元素的值置0,再将_size--即可
	psl->_size--;
}

 //在顺序表头部插入一个元素,时间复杂度为O(N) 
void SeqListPushFront(SeqList* psl, SLDataType x)
{//在顺序表头部插入数据
	assert(psl); 
	int end = psl->_size-1;
	while (end>=0)
	{
		psl->array[end + 1] = psl->array[end];//将元素整体向后移动
		end--;
	}
	psl->array[0] = x;//再将元素插入头部
	psl->_size++;
}

//删除顺序表头部的元素,时间复杂度为O(N)
void SeqListPopFront(SeqList* psl)
{
	assert(psl);
	//将第二个数据依次向前移动
	for (size_t i = 0; i < psl->_size - 1; i++)
	{
		psl->array[i] = psl->array[i + 1];
	}
	psl->_size--;

}

 //在顺序表中查找一个值为x的元素,找到返回该元素下标,找不到返回-1
int SeqListFind(SeqList* psl, SLDataType x)
{
	assert(psl);
	for (size_t i = 0; i < psl->_size - 1; i++)
	{
		if (psl->array[i] == x)//遍历顺序表,查找是否有值与x相等的元素
			return i;
	}
	return -1;
}

//在顺序表指定位置插入一个值为x的元素,时间复杂度接近O(N)
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x)
{
	    assert(psl&&pos <= psl->_size);
		CheckCapacity(psl);//插入元素之前都得判断是否需要增容
		int end = psl->_size - 1;
		while (end >= (int)pos)
		{
			psl->array[end + 1] = psl->array[end];//将pos及pos之后的数向后移动,再将值插入pos处
			end--;
		}
		psl->array[pos] = x;
	    psl->_size++;
}

//删除顺序表指定位置的元素,时间复杂度接近O(N)
void SeqListErase(SeqList* psl, size_t pos)
{
	assert(psl&&pos<psl->_size);
	while (pos<psl->_size)
	{
		psl->array[pos] = psl->array[pos + 1];
		pos++;
	}
	psl->_size--;

}

  //删除顺序表中值为x的元素
void SeqListRemove(SeqList* psl, SLDataType x)
{
	assert(psl);
	int pos = SeqListFind(psl, x);//通过find找到元素的位置,再进行删除即可
	if (pos != -1)
	{
		while (pos < (int)psl->_size)
		{
			psl->array[pos] = psl->array[pos + 1];
			pos++;
		}
		psl->_size--;
	}
	else
		printf("删除的数不存在!\n");
}

//修改顺序表中元素
void SeqListModify(SeqList* psl, size_t pos, SLDataType x)
{
	assert(psl && pos < psl->_size);
	psl->array[pos] = x;
}

//对顺序表中的元素进行冒泡排序,使其有序
void SeqListBubbleSort(SeqList* psl)
{
	assert(psl);
	size_t finish = psl->_size;
	while (finish>0)
	{
		for (size_t i = 0; i < finish; i++)
		{
			if (psl->array[i - 1]>psl->array[i])
			{
				SLDataType temp = psl->array[i];
				psl->array[i] = psl->array[i - 1];
				psl->array[i - 1] = temp;
			}
		}
		finish--;
	}
	
}
//通过二分查找顺序中值为x的元素
int  SeqListBinaryFind(SeqList* psl, SLDataType x)
{
	assert(psl);
	int mid;
	int begin = 0;
	int end = psl->_size-1;
	while (begin <= end)
	{
		mid = begin + (end - begin) / 2;
		if (psl->array[mid] > x)
		{
			end = mid - 1;
		}
		else if (psl->array[mid] < x)
		{
			begin = mid + 1;
		}
		else
			return mid;
	}
	if (begin>end)
		return -1;
	else
		return mid;

}
//移除顺序表中所有的元素,即清空顺序表
void SeqListRmoveAll(SeqList* psl, SLDataType x)
{
	assert(psl);
	size_t cur = 0;
	size_t dst = 0;
	while (cur < psl->_size-1)
	{
		if (psl->array[cur] != x)
		{
			psl->array[dst] = psl->array[cur];
			++dst;
		}
		++cur;
	}
	psl->_size = dst;

}
void SeqListtest1()
{
	SeqList s;
	SeqListInit(&s, 2);
	SeqListPushBack(&s, 5);
	SeqListPushBack(&s, 1);
	SeqListPushBack(&s, 2);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 6);
	SeqListPushBack(&s, 3);
	SeqListPushBack(&s, 4);
	SeqListPushBack(&s, 3);
	//SeqListPrint(&s);
	//SeqListPopBack(&s);
	//SeqListPushFront(&s, 3);
	//SeqListPopFront(&s);
	//SeqListInsert(&s, 2, 3);
	//SeqListErase(&s, 2);
	//SeqListRemove(&s, 5);
	//SeqListModify(&s, 2, 1);
	//SeqListBubbleSort(&s);
	/*int ret = SeqListBinaryFind(&s, 2);
	if (ret = -1)
	{
		printf("找不到\n");
	}
	else
		printf("所找的数的下标为:", ret);*/
	SeqListRmoveAll(&s, 3);
	SeqListPrint(&s);
}

http://www.niftyadmin.cn/n/1280928.html

相关文章

Java学习进度(2013.03.12)—Struts2学习二

在使用struts2的方法之前&#xff0c;必须拷贝jar包到lib文件夹下。 jar包的目录如下&#xff1a; asm-3.3.jar asm-commons-3.3.jar asm-tree-3.3.jar commons-fileupload-1.2.2.jar commons-io-2.0.1.jar commons-lang3-3.1.jar freemarker-2.3.19.jar javassist-3.11.0.GA.j…

【数据结构】—— 无头单向不循环链表相关接口实现

一、链表基本概念 1、链表的分类&#xff08;8种&#xff09; 单向 | 双向有头 | 没有头有循环 | 无循环可随机组合 2、顺序表与链表的区别 3、相关接口介绍 接口功能void SListInit(SList* plist)初始化链表void SListDstory(SList* plist)销毁链表SListNode* BuySListNod…

leetcode1218:最长定差子序列

leetcode1218&#xff1a;最长定差子序列 思路&#xff1a;动态规划 我们从左往右遍历arr&#xff0c;并计算出以arr[i] 为结尾的最长的等差子序列的长度&#xff0c;取所有长度的最大值&#xff0c;即为答案,使用dp[i]表示arr[i]为结尾的最长的等差子序列的长度&#xff0c;我…

经典算法题-球和篮子

1.问题描述 Problem Statement 问题描述 ???? You have several identical balls that you wish to place in several baskets. Each basket has the same maximum capacity. You are given an int baskets, the number of baskets you have. You are given an int capacit…

【数据结构】—— 带头双向循环链表相关接口的实现

双向链表的概念 双向链表也叫双链表&#xff0c;是链表的一种&#xff0c;它的每个数据结点中都有两个指针&#xff0c;分别指向直接后继和直接前驱。所以&#xff0c;从双向链表中的任意一个结点开始&#xff0c;都可以很方便地访问它的前驱结点和后继结点。一般我们都构造双…

何凯明最新一作:Masked Autoencoders Are Scalable Vision Learners

Masked Autoencoders Are Scalable Vision Learners 何凯明大神最新一作&#xff0c;mask输入图像的随机patch&#xff0c;并重建移除的像素。 主要提出两点&#xff1a; 1.提出一种非对称的编码器-解码器 2.mask高比例的输入图像patch将变成一个不错且有意义的自监督任务 摘要…

统计某个单词出现次数

引用Microsoft VBScript Regular Expressions 1.0统计单词出现次数 Private Function TongJi(ByVal T_txt As String) As LongDim cnt As LongDim re As RegExpDim mhs As MatchCollectionSet re New RegExpre.IgnoreCase Falsere.Global TrueDim strLine As StringOpen &qu…

经典算法题-抛石头

1.问题描述 Problem Statement 问题陈述When a stone is thrown across water, sometimes it will land on the water and bounce rather than falling in right away. Suppose that a stone is thrown a distance of n. On each successive bounce it will travel half the d…