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

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)
顺序表 数据结构 顺序表基本操作 C语言实现 顺序表详解_第1张图片
int removeElement(int* nums, int numsSize, int val){
       int j=-1;
       for(int i=0;i

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

实例2

删除排序数组中的重复项
顺序表 数据结构 顺序表基本操作 C语言实现 顺序表详解_第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

合并两个有序数组
顺序表 数据结构 顺序表基本操作 C语言实现 顺序表详解_第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.头部或中间插入删除不需要挪动数据

你可能感兴趣的:(C语言数据结构,c语言,数据结构,leetcode,算法,visual,studio)