分类
静态顺序表
//静态顺序表,少了不够用,多了浪费
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--;
}
}