数据结构(顺序表)

本文详细介绍了C语言中的静态和动态顺序表结构,包括它们的定义、初始化、插入、删除、扩容以及查找等操作,同时展示了如何使用尾插、头插和双指针法等技巧。
摘要由CSDN通过智能技术生成

分类

静态顺序表

//静态顺序表,少了不够用,多了浪费
typedef int SLDataType;
#define N 7
typedef struct SList
{
	SLDataType a[N];//定长数组
	int size;//有效数据个数
}SL;

动态顺序表

//动态顺序表,可扩容
typedef int SLDataType;
typedef struct SList
{
	SLDataType* arr;
	int size;//有效数据个数
	int capacity;//空间容量
}SL;

顺序表的各项操作

顺序表初始化(传地址)

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

typedef int SLDataType;
typedef struct SListNode
{
	SLDataType* arr;
	int size;
	int capacity;
}SL;

void SLInit(SL* ps)//顺序表初始化
{
	ps->arr = NULL;//结构体指针调用数据用"->"
	ps->size = ps->capacity = 0;
}
void sl1()
{
	SL s;//结构体s
	SLInit(&s);//传递结构体s的地址
}
int main()
{
	sl1();
	return 0;
}

错误方法:传值

 

 顺序表的插入

空间不够需要扩容

void SLCheckCapacity(SL* ps)//扩容
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//初始化了ps->capacity,所以判断空间
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * newcapacity);//因为是扩容ps->arr的空间,所以指针变量的返回类型为SLDataType*
		if (tmp == NULL)               //realloc将已有空间扩容
		{
			perror("realloc");
			return;
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}

 realloc操作原理

尾插 

void SLPushBack(SL* ps, SLDataType x)//尾插
{
	assert(ps);//断言,若ps为空,则无法插入数据
	SLCheckCapacity(ps);//需要判断空间是否需要扩容
	ps->arr[ps->size++] = x;
}

断言的作用 

 

 头插

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = ps->size; i > 0; i--)//将数据往后挪动一位
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;//头插
	ps->size++;
}

 顺序表的删除

尾删

void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);//数据个数不能为0,否则无法进行删除
	ps->size--;
}

头删

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i+1];
	}
	ps->size--;
}

顺序表指定位置的操作

插入

void SLInsert(SL* ps, int pos,SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);//防止在超出顺序表的位置进行删除操作是系统崩溃
	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//pos之后的数据往后挪动一位
	}
	ps->arr[pos] = x;//pos处插入x
	ps->size++;
}

 删除

pos后的数据向前挪动一位

void SLErase(SL* ps,int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	for (int i = pos; i < ps->size; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

顺序表的销毁

void SLDestroy(SL* ps)
{
	assert(ps);
	if (ps->arr)//如果顺序表为空,可以不必要销毁
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

顺序表的查找 

//顺序表中查找x
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
			return i;
	}
	return -1;
}

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

typedef int SLDataType;
typedef struct SListNode
{
	SLDataType* arr;
	int size;
	int capacity;
}SL;

void SLInit(SL* ps)
{
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}
void SLCheckCapacity(SL* ps)//扩容
{
	if (ps->size == ps->capacity)
	{
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//初始化了ps->capacity,所以判断空间
		SLDataType* tmp = (SLDataType*)realloc(ps->arr, sizeof(SLDataType) * newcapacity);//因为是扩容ps->arr的空间,所以指针变量的返回类型为SLDataType*
		if (tmp == NULL)               //realloc将已有空间扩容
		{
			perror("realloc");
			return;
		}
		ps->arr = tmp;
		ps->capacity = newcapacity;
	}
}
void SLPushBack(SL* ps, SLDataType x)//尾插
{
	assert(ps);//断言,若ps为空,则无法插入数据
	SLCheckCapacity(ps);//需要判断空间是否需要扩容
	ps->arr[ps->size++] = x;
}
void SLPrint(SL* ps)
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->arr[i]);
	}
	printf("\n");
}
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = ps->size; i > 0; i--)//将数据往后挪动一位
	{
		ps->arr[i] = ps->arr[i - 1];
	}
	ps->arr[0] = x;//头插
	ps->size++;
}
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);//数据个数不能为0,否则无法进行删除
	ps->size--;
}
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < ps->size - 1; i++)
	{
		ps->arr[i] = ps->arr[i+1];
	}
	ps->size--;
}
void SLInsert(SL* ps, int pos,SLDataType x)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);//防止在超出顺序表的位置进行删除操作是系统崩溃
	SLCheckCapacity(ps);
	for (int i = ps->size; i > pos; i--)
	{
		ps->arr[i] = ps->arr[i - 1];//pos之后的数据往后挪动一位
	}
	ps->arr[pos] = x;//pos处插入x
	ps->size++;
}
void SLErase(SL* ps,int pos)
{
	assert(ps);
	assert(pos >= 0 && pos <= ps->size);
	for (int i = pos; i < ps->size; i++)
	{
		ps->arr[i] = ps->arr[i + 1];
	}
	ps->size--;
}

void SLDestroy(SL* ps)
{
	assert(ps);
	if (ps->arr)//如果顺序表为空,可以不必要销毁
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capacity = 0;
}

//顺序表中查找x
int SLFind(SL* ps, SLDataType x)
{
	assert(ps);
	for (int i = 0; i < ps->size; i++)
	{
		if (ps->arr[i] == x)
			return i;
	}
	return -1;
}
void sl1()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushBack(&s, 4);
	SLPrint(&s);
	SLPushFront(&s, 100);
	SLPrint(&s);
	SLPopBack(&s);
	SLPrint(&s);
	SLPopFront(&s);
	SLPrint(&s);
	SLInsert(&s, 2, 1000);
	SLPrint(&s);
	SLErase(&s, 2);
	SLPrint(&s);
	SLDestroy(&s);
}

void sl2()
{
	SL s;
	SLInit(&s);
	SLPushBack(&s, 1);
	SLPushBack(&s, 2);
	SLPushBack(&s, 3);
	SLPushBack(&s, 4);
	SLPrint(&s);
	//int ret=SLFind(&s, 2);
	int ret=SLFind(&s, 100);
	if (ret >= 0)
	{
		printf("要查找的数的下标:%d", ret);
	}
	else
	{
		printf("fail!!!");
	}
}
int main()
{
	//sl1();
	sl2();
	return 0;
}

Leetcode运用

移除元素

int removeElement(int* nums, int numsSize, int val) //双指针法
{
   int dst=0,src=0;
   while(src<numsSize)
   {
        if(nums[src]==val)//当“src"找到val,向后走
        {
            src++;
        }
        else              //当找到的不为val时,将dst现在指的val替换
        {
            nums[dst]=nums[src];
            dst++;
            src++;
        }
   }
   return dst;
}

合并两个有序数组

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) 
{
    int l1=m-1;
    int l2=n-1;
    int l3=m+n-1;
    while(l1>=0&&l2>=0)
    {
        if(nums1[l1]>nums2[l2])
        {
            nums1[l3]=nums1[l1];
            l3--;
            l1--;
        }
        else
        {
            nums1[l3]=nums2[l2];
            l3--;
            l2--;
        }
    }
    while(l1<0&&l2>=0)//当l2走完,l1未走完,即nums1已经排好序,所以只需要讨论l2未走完时需要继续排序
    {
        nums1[l3]=nums2[l2];
        l2--;
        l3--;
    }
}

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值