顺序表 数据结构 顺序表基本 *** 作 C语言实现 顺序表详解

顺序表 数据结构 顺序表基本 *** 作 C语言实现 顺序表详解,第1张

1.线性表 线性表 linear list n 个具有相同特性的数据元素的有限序列,线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 ... 线性表在逻辑上是线性结构,也就说是连续的一条直线,但是在物理结构上并不一定是连续的, 线性表在物理上存储时,通常以数组和链式结构的形式存储 2.顺序表 2.1概念及结构

顺序表就是数组,但是数据必须从第一个位置开始连续存储

顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存 储,在数组上完成数据的增删查改 1. 静态顺序表

使用定长数组存储元素

#define N 200
typedef int SLDataType;
struct SeqList
{
    SLDataType a[N];//定义一个数组
    int size;//数据个数
};

 N太小可能不够用,N太大可能浪费空间

2. 动态顺序表 使用动态开辟的数组存储
#define SEQ_INIT_SIZE 10//初始容量
#define SEQ_INC_SIZE 2//每次增容的倍数
typedef struct SeqList
{
    SLDataType* a;//指向动态数组指针
    int sz;//数据个数
    int capacity;//容量 -空间大小
}SeqList;

空间不够则增容

2.2 接口实现 
#include
#include
#include
#include
#define SEQ_INIT_SIZE 10//初始容量
#define SEQ_INC_SIZE 2//每次增容的倍数
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
#define NULLPTR -3
typedef int status;//状态
typedef int SLDataType;//元素类型
1.顺序表初始化
void SeqListInit(SeqList* ps)
{
	assert(ps != NULL);
	ps->capacity = SEQ_INIT_SIZE;
	ps->sz = 0;
	ps->a = (SLDataType*)malloc(sizeof(SLDataType) * ps->capacity);
	if (ps->a == NULL)exit(-1);
}
2.打印顺序表
void SeqListPrint(const SeqList* ps)
{
	assert(ps != NULL);
	for (int i = 0; i < ps->sz; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n");
}
3.查找某元素返回下标
int SeqListFind(const SeqList* ps, SLDataType x)
{
	assert(ps != NULL);
	for (int i = 0; i < ps->sz; i++)
	{
		if (ps->a[i] == x)return i;
	}
	return -1;
}
4.顺序表增容(malloc)
bool IncCapacity(SeqList* ps)
{
	assert(ps != NULL);
	int newcapacity = ps->capacity * SEQ_INC_SIZE;
	SLDataType* newdata = (SLDataType*)malloc(sizeof(SLDataType) * newcapacity);
	if (newdata == NULL)return false;
	for (int i = 0; i < ps->capacity; i++)
	{
		newdata[i] = ps->a[i];
	}
	free(ps->a);
	ps->a = newdata;
	ps->capacity = newcapacity;
	return true;
}
5.顺序表增容(realloc) 
bool IncCapacity(SeqList* ps)
{
	assert(ps != NULL);
	int newcapacity = ps->capacity * SEQ_INC_SIZE;
	SLDataType* newdata = (SLDataType*)realloc(ps->a,sizeof(SLDataType) * newcapacity);
	if (newdata == NULL)return false;
	ps->a = newdata;
	ps->capacity = newcapacity;
	return true;
}
6.顺序表判满
bool IsFull(const SeqList* ps)
{
	assert(ps != NULL);
	return ps->sz == ps->capacity;
}
7.在pos位置插入x
status SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
	assert(ps != NULL);
	if (pos<0 || pos>ps->sz)return INFEASIBLE;
	if (IsFull(ps) && !IncCapacity(ps))return OVERFLOW;//没满和满了但增容成功都不return,满了但增容失败return
	for (int i = ps->sz - 1; i >= pos; i--)
	{
		ps->a[i + 1] = ps->a[i];
	}
	ps->a[pos] = x;
	ps->sz++;
	return OK;
}
8.顺序表尾插
void SeqListPushBack(SeqList* ps, SLDataType x)
{
	assert(ps != NULL);
	SeqListInsert(ps, ps->sz, x);
}
9.顺序表头插
void SeqListPushFront(SeqList* ps, SLDataType x)
{
	assert(ps != NULL);
	SeqListInsert(ps, 0, x);
}
10.删除pos位置元素 
status SeqListErase(SeqList* ps,int pos)
{
	assert(ps != NULL);
	if (pos<0 || ps>ps->sz - 1)return INFEASIBLE;
	for (int i = pos; i < ps->sz-1; i++)
	{
		ps->a[i] = ps->a[i + 1];
	}
	ps->sz--;
	return OK;
}
11.顺序表尾删
void SeqListPopBack(SeqList* ps)
{
	assert(ps != NULL);
	SeqListErase(ps,ps->sz-1);
}
12.顺序表头删 
void SeqListPopFront(SeqList* ps)
{
	assert(ps != NULL);
	SeqListErase(ps,0);
}
13.顺序表清空
void SeqListClear(SeqList* ps)
{
    assert(ps != NULL);
    ps->sz = 0;
}
14.顺序表销毁
void SeqListDestory(SeqList* ps)
{
    assert(ps != NULL);
    ps->capacity = 0;
    ps->sz = 0;
    free(ps->a);
} 
2.3 数组相关面试题 实例1 原地移除数组中所有的元素 val ,要求时间复杂度为 O(N) ,空间复杂度为 O(1)
int removeElement(int* nums, int numsSize, int val){
       int j=-1;
       for(int i=0;i

 2个指针,把不删的向前移把要删的覆盖了,1个指针始终指着不删的下标,另一个指针游历判断删不删,最后指着不删的下标的指针+1是剩下元素的个数

实例2 删除排序数组中的重复项
int removeDuplicates(int* nums, int numsSize){
     int i=0,j=0;
     while(j!=numsSize)
     {
         if(nums[i]==nums[j])
         {
             j++;
         }
         else
         {
             i++;
             nums[i]=nums[j];
             j++;    
         }      
     }
     return i+1;
}
 实例3 合并两个有序数组
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
      int i=m-1;
      int j=n-1;
      int k=m+n-1;
      while(i>=0&&j>=0)
      {
          nums1[k--]=nums1[i]>=nums2[j]?nums1[i--]:nums2[j--];
      }
      while(j>=0)
      {
          nums1[k--]=nums2[j--];
      }
}
2.4 顺序表的问题 问题:

1. 中间/头部的插入删除,效率低,时间复杂度为O(N)

2. 增容需要申请新空间,拷贝数据,释放旧空间会有不小的消耗 3. 增容一般是呈2倍的增长,势必会有一定的空间浪费,例如当前容量为100,满了以后增容到 200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间 改善方案:

1.按申请释放空间

2.头部或中间插入删除不需要挪动数据

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/787579.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)