【数据结构】顺序表

目录

一 概念及结构

二  顺序表接口实现

1 管理数据 增删查改(SeqList.c)

2 尾插(SeqList.c)

3 尾删(SeqList.c)

4 头插(SeqList.c)

5 头删(SeqList.c)

6 在pos位置插入x(SeqList.c)

7 在pos位置删除x(SeqList.c)

8 修改pos位置上的值(SeqList.c)

三 练习题(OJ) 

1 移除元素

2 合并两个有序数组

3 删除有序数组的重复项


一 概念及结构

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

顺序表一般可以分为:

1. 静态顺序表:使用定长数组存储元素

【数据结构】顺序表_第1张图片

2. 动态顺序表:使用动态开辟的数组存储

【数据结构】顺序表_第2张图片

二  顺序表接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表。

先用SeqList.h 把我们想要的接口写进来

#pragma once

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include
#include
#include

// 动态顺序表
typedef int SLDataType;

typedef struct SeqList
{
       SLDataType* a;
       int size;        // 存储有效数据个数
       int capacity;    // 空间大小
}SL;

// 管理数据 -- 增删查改
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLCheckCapacity(SL* ps);

// 头插头删 尾插尾删
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);




// 返回下标,没有找打返回-1
int SLFind(SL* ps, SLDataType x);

// 在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x);

// 删除pos位置的值
void SLErase(SL* ps, int pos);

//修改
void SLModify(SL* ps, int pos, SLDataType x);

1 管理数据 增删查改(SeqList.c)

#include"SeqList.h"

//初始化

void SLInit(SL* ps)
{
       assert(ps);//断言 防止是空指针

       ps->a = (SLDataType*)malloc(sizeof(SLDataType) * 4);
       if (ps->a == NULL)
       {
              perror("malloc failed");
              exit(-1);
              //return;
       }

       ps->size = 0;
       ps->capacity = 4;
}


//销毁
void SLDestroy(SL* ps)
{
       assert(ps);

       free(ps->a);
       ps->a = NULL;
       ps->capacity = ps->size = 0;
}


//打印
void SLPrint(SL* ps)
{
       assert(ps);

       for (int i = 0; i < ps->size; i++)
       {
              printf("%d ", ps->a[i]);
       }
       printf("\n");
}


//扩容
void SLCheckCapacity(SL* ps)
{
       assert(ps);

       // 满了要扩容
       if (ps->size == ps->capacity)
       {
              SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * 
(sizeof(SLDataType)));//一般都是1.5倍 2倍的扩
              if (tmp == NULL)
              {
                      perror("realloc failed");
                      exit(-1);
              }

              ps->a = tmp;
              ps->capacity *= 2;
       }
}

2 尾插(SeqList.c)

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);//检查是否要扩容
	ps->a[ps->size] = x;
	ps->size++;

}

【数据结构】顺序表_第3张图片

  测试(Test.c)

void Test1()
{
	SL s1;
	SLInit(&s1);
	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4);
	SLPushBack(&s1, 5);
	SLPrint(&s1);
	SLDestroy(&s1);

}

int main()
{
	Test1();
	return 0;
}

 【数据结构】顺序表_第4张图片

3 尾删(SeqList.c)

//尾删
void SLPopBack(SL* ps)
{
    assert(ps);
    assert(ps->size > 0);
    //ps->a[ps->size-1] = 0;
    ps->size--;
}

 【数据结构】顺序表_第5张图片

【数据结构】顺序表_第6张图片

4 头插(SeqList.c)

//头插
void SLPushFront(SL* ps, SLDataType x)
{
    assert(ps);
    SLCheckCapacity(ps);
    int tmp = ps->size;
    while (tmp > 0)
    {
        ps->a[tmp] = ps->a[tmp - 1];
        tmp--;
    }
    ps->a[0] = x;
    ps->size++;
}

【数据结构】顺序表_第7张图片 

【数据结构】顺序表_第8张图片 

5 头删(SeqList.c)

//头删
void SLPopFront(SL* ps)
{
    assert(ps);
    assert(ps->size > 0);
    int begin = 1;
    while (begin < ps->size)
    {
        ps->a[begin - 1] = ps->a[begin];
        begin++;
    }
    ps->size--;
}

 【数据结构】顺序表_第9张图片

【数据结构】顺序表_第10张图片

6 在pos位置插入x(SeqList.c)

// 在pos位置插入x
void SLInsert(SL* ps, int pos, SLDataType x)
{
    assert(ps);
    assert(pos >= 0 && pos<= ps->size);
    SLCheckCapacity(ps);
    int end = ps->size;

    while (end > pos)
    {
        ps->a[end] = ps->a[end - 1];
        end--;
    }
    ps->a[pos] = x;
    ps->size++;
    
}

 【数据结构】顺序表_第11张图片

 【数据结构】顺序表_第12张图片

7 在pos位置删除x(SeqList.c)

// 删除pos位置的值
void SLErase(SL* ps, int pos)
{
    assert(ps);
    assert(pos >= 0 && pos size);
    SLCheckCapacity(ps);
    while (pos < ps->size)
    {
        ps->a[pos] = ps->a[pos + 1];
        pos++;
    }
    ps->size--;
}

 【数据结构】顺序表_第13张图片

【数据结构】顺序表_第14张图片

8 修改pos位置上的值(SeqList.c)

//修改pos位置的值
void SLModify(SL * ps, int pos, SLDataType x)
{
    assert(ps);
    assert(pos >= 0 && pos < ps->size);
    ps->a[pos] = x;
}

总结:在实际的使用中 尾插尾删 头插头删 都可以使用SLInsert  和 SLErase 的方法 

 

三 练习题(OJ) 

1 移除元素

27. 移除元素 - 力扣(LeetCode)

【数据结构】顺序表_第15张图片

int removeElement(int* nums, int numsSize, int val) {
	int src = 0;
	int dst = 0;
	while (src < numsSize)
	{
		if (nums[src] != val)
		{
			nums[dst] = nums[src];
			dst++;
		}
		src++;
	}
	return dst;

}

 【数据结构】顺序表_第16张图片

2 合并两个有序数组

88. 合并两个有序数组 - 力扣(LeetCode)

思路就是将大的尾插到长的数组里

【数据结构】顺序表_第17张图片

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
	int end1 = m - 1; int end2 = n - 1; int end = m + n - 1;
	while (end1 >= 0 && end2 >= 0)
	{
		if (nums1[end1] < nums2[end2])
		{
			nums1[end] = nums2[end2];
			end2--;
		}
		else
		{
			nums1[end] = nums1[end1];
			end1--;
		}
		end--;
	}
	while (end2 >= 0)
	{
		nums1[end] = nums2[end2];
		end--;
		end2--;
	}

}

 3 删除有序数组的重复项

【数据结构】顺序表_第18张图片

 思路就是定义两个变量 

int removeDuplicates(int* nums, int numsSize){
    int src=0, dst = 0;
    while(src < numsSize)
    {
        if(nums[src] == nums[dst])
        {
            src++;
        }
        else
        {
            dst++;
            nums[dst] = nums[src];
            src++;
        }
    }
    return dst+1;

}

你可能感兴趣的:(数据结构,c语言)