数据结构之顺序表

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

静态顺序表:

#define  N 1000
typedef int SLDataType;//重新定义容易更改类型

//静态顺序表 
typedef struct SeqList
{
	SLDataType a[N];
	int size;//表示数组存储了多少个数据
}SL;

动态顺序表:

typedef int SLDataType;

//动态顺序表 
typedef struct SeqList
{
	SLDataType* a;
	int size;//表示数组存储了多少个数据
	int capacity;//数组实际能存数据的空间容量大小
}SL;

接口:

//接口函数  
void SeqListCheckCapacity(SL* ps);//核查容量
void SeqListPrint(SL* ps);//打印
void SeqListDestory(SL* ps);//内存销毁
void SeqListInit(SL* ps);//顺序表初始化
void SeqListPushBack(SL* ps, SLDataType x);//尾插
void SeqListPopBack(SL* ps);//尾删
void SeqListPushFront(SL* ps, SLDataType x);//头插
void SeqListPopFront(SL* ps);//头删

//找到了返回x位置下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x);
//指定pos下标位置插入
void SeqListInsert(SL* ps,int pos, SLDataType x);
//删除pos位置的数据
void SeqListErase(SL* ps,int pos);

1.核查容量:

void SeqListCheckCapacity(SL* ps)
{
	//如果容量不够,我们就进行扩容
	if (ps->size == ps->capacity)
	{
		//如果开始容量为0,则新容量变为4,其他的变为原来的2倍
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//realloc 如果最开始指针为NULL,那么相当于malloc
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}

2.打印函数

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

3.顺序表销毁

void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

4.指定pos下标进行插入函数
 

//指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	//检查位置是否合理
	assert(pos >= 0 && pos <= ps->size);
	//插入前要检查一下容量是否足够
	SeqListCheckCapacity(ps);
	//pos位置向后移动一个位置
	int end = ps->size -1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

5.删除pos位置的数据函数

//删除pos位置的数据
void SeqListErase(SL* ps, int pos)
{
	//检查位置是否合理
	assert(pos >= 0 && pos < ps->size);
	//检查是否有数据可以删除
	assert(ps->size);
	int end = pos;
	while (end < ps->size - 1)
	{
		ps->a[end] = ps->a[end + 1];
		end++;
	}
	ps->size--;
}

6.顺序表初始化


void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

7.尾插


void SeqListPushBack(SL* ps, SLDataType x)
{
	1.容量足够,直接插入
	2.容量不够,扩容
	3.整个顺序表没有空间
	//SeqListCheckCapacity(ps);
	//
	容量够了,那么就直接放进去
	//ps->a[ps->size] = x;
	//ps->size++;
	SeqListInsert(ps,ps->size,x);
}

8.尾删

//尾删
void SeqListPopBack(SL* ps)
{
	//温柔的方式解决
	//if (ps->size > 0)
	//{
	//	ps->size--;
	//}

	//暴力的解决方式
	//assert(ps->size > 0);//如果有效位数<0就会报错
	//ps->size--;
	SeqListErase(ps,ps->size-1);
}

9.前插

//前插
void SeqListPushFront(SL* ps, SLDataType x)
{
//	SeqListCheckCapacity(ps);
//	//设置一个尾指针,从后往前移动
//	int end = ps->size -1;//end表示下标
//	while (end >= 0)
//	{
//		ps->a[end + 1] = ps->a[end];
//		end--;
//	}
//	ps->a[0] = x;
//	ps->size++;
	SeqListInsert(ps,0,x);
}

10.头删

//头删
void SeqListPopFront(SL* ps)
{
	//要有得删
	//assert(ps->size);
	从第二个向前移动
	//int begin = 0;
	//int i = 0;
	//while(begin < ps->size-1)
	//{
	//	ps->a[begin] = ps->a[begin + 1];
	//	begin++;
	//}
	//ps->size--;
	SeqListErase(ps,0);

}

11.寻找下标函数

//找到了返回x位置下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{
	int i = 0;
	for (i = 0;i < ps->size;i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}

SeqList.h

#pragma once

//#define  N 1000
//typedef int SLDataType;
//
静态顺序表 
//typedef struct SeqList
//{
//	SLDataType a[N];
//	int size;//表示数组存储了多少个数据
//}SL;
//
//void SeqListPushBack(SL *ps,SLDataType x);


#include<stdio.h>
#include<assert.h>
typedef int SLDataType;

//动态顺序表 
typedef struct SeqList
{
	SLDataType* a;
	int size;//表示数组存储了多少个数据
	int capacity;//数组实际能存数据的空间容量大小
}SL;

void SeqListCheckCapacity(SL* ps);
void SeqListPrint(SL* ps);
void SeqListDestory(SL* ps);
//接口函数  
void SeqListInit(SL* ps);
void SeqListPushBack(SL* ps, SLDataType x);
void SeqListPopBack(SL* ps);
void SeqListPushFront(SL* ps, SLDataType x);
void SeqListPopFront(SL* ps);

//找到了返回x位置下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x);
//指定pos下标位置插入
void SeqListInsert(SL* ps,int pos, SLDataType x);
//删除pos位置的数据
void SeqListErase(SL* ps,int pos);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"

void SeqListCheckCapacity(SL* ps)
{
	//如果容量不够,我们就进行扩容
	if (ps->size == ps->capacity)
	{
		//如果开始容量为0,则新容量变为4,其他的变为原来的2倍
		int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		//realloc 如果最开始指针为NULL,那么相当于malloc
		SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
		if (tmp == NULL)
		{
			printf("realloc fail\n");
			exit(-1);
		}
		ps->a = tmp;
		ps->capacity = newcapacity;
	}
}
void SeqListPrint(SL* ps)
{
	int i = 0;
	for (i = 0;i < ps->size;i++)
	{
		printf("%d ",ps->a[i]);
	}
	printf("\n");
}
void SeqListDestory(SL* ps)
{
	free(ps->a);
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}
//指定pos下标位置插入
void SeqListInsert(SL* ps, int pos, SLDataType x)
{
	//检查位置是否合理
	assert(pos >= 0 && pos <= ps->size);
	//插入前要检查一下容量是否足够
	SeqListCheckCapacity(ps);
	//pos位置向后移动一个位置
	int end = ps->size -1;
	while (end >= pos)
	{
		ps->a[end + 1] = ps->a[end];
		end--;
	}
	ps->a[pos] = x;
	ps->size++;
}

//删除pos位置的数据
void SeqListErase(SL* ps, int pos)
{
	//检查位置是否合理
	assert(pos >= 0 && pos < ps->size);
	//检查是否有数据可以删除
	assert(ps->size);
	int end = pos;
	while (end < ps->size - 1)
	{
		ps->a[end] = ps->a[end + 1];
		end++;
	}
	ps->size--;
}

void SeqListInit(SL* ps)
{
	ps->a = NULL;
	ps->size = ps->capacity = 0;
}

void SeqListPushBack(SL* ps, SLDataType x)
{
	1.容量足够,直接插入
	2.容量不够,扩容
	3.整个顺序表没有空间
	//SeqListCheckCapacity(ps);
	//
	容量够了,那么就直接放进去
	//ps->a[ps->size] = x;
	//ps->size++;
	SeqListInsert(ps,ps->size,x);
}

//尾删
void SeqListPopBack(SL* ps)
{
	//温柔的方式解决
	//if (ps->size > 0)
	//{
	//	ps->size--;
	//}

	//暴力的解决方式
	//assert(ps->size > 0);//如果有效位数<0就会报错
	//ps->size--;
	SeqListErase(ps,ps->size-1);
}

//前插
void SeqListPushFront(SL* ps, SLDataType x)
{
//	SeqListCheckCapacity(ps);
//	//设置一个尾指针,从后往前移动
//	int end = ps->size -1;//end表示下标
//	while (end >= 0)
//	{
//		ps->a[end + 1] = ps->a[end];
//		end--;
//	}
//	ps->a[0] = x;
//	ps->size++;
	SeqListInsert(ps,0,x);
}

//头删
void SeqListPopFront(SL* ps)
{
	//要有得删
	//assert(ps->size);
	从第二个向前移动
	//int begin = 0;
	//int i = 0;
	//while(begin < ps->size-1)
	//{
	//	ps->a[begin] = ps->a[begin + 1];
	//	begin++;
	//}
	//ps->size--;
	SeqListErase(ps,0);

}

//找到了返回x位置下标,没有找到返回-1
int SeqListFind(SL* ps, SLDataType x)
{
	int i = 0;
	for (i = 0;i < ps->size;i++)
	{
		if (ps->a[i] == x)
		{
			return i;
		}
	}
	return -1;
}


Test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"


void menu()
{
	printf("***********************************************\n");
	printf("  1. 尾插   2. 尾删   3.头插  ***********\n");
	printf("   4.头删   5. 打印   0.退出            ***********\n");
	printf("***********************************************\n");

}
enum Option
{
	EXIT,
	PushBack,
	PopBack,
	PushFront,
	PopFront,
	print
};
//void SeqListTest1()
//{
//	SL s1;
//	SeqListInit(&s1);
//	SeqListPushBack(&s1,1);
//	SeqListPushBack(&s1,2);
//	SeqListPushBack(&s1,3);
//	SeqListPushBack(&s1,4);
//	SeqListPushBack(&s1,5);
//	SeqListPrint(&s1);
//	SeqListPopBack(&s1);
//	SeqListPopBack(&s1);
//	SeqListPopBack(&s1);
//	SeqListPrint(&s1);
//
//	SeqListDestory(&s1);
//}

//void SeqListTest2()
//{
//	SL s1;
//	SeqListInit(&s1);
//	SeqListPushBack(&s1, 1);
//	SeqListPushBack(&s1, 2);
//	SeqListPushBack(&s1, 3);
//	SeqListPushBack(&s1, 4);
//	SeqListPushBack(&s1, 5);
//	
//	SeqListPushFront(&s1,10);
//	SeqListPushFront(&s1, 20);
//	SeqListPushFront(&s1, 30);
//	SeqListPrint(&s1);
//	/*SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPrint(&s1);*/
//	int ret = SeqListFind(&s1, 10);
//	SeqListInsert(&s1,ret,50);
//	SeqListPrint(&s1);
//	SeqListErase(&s1,2);
//	SeqListPrint(&s1);
//	SeqListInsert(&s1, 0, 50);
//	SeqListPrint(&s1);
//	SeqListDestory(&s1);
//}

//void SeqListTest2()
//{
//	SL s1;
//	SeqListInit(&s1);
//	SeqListPushBack(&s1, 1);
//	SeqListPushBack(&s1, 2);
//	SeqListPushBack(&s1, 3);
//	SeqListPushBack(&s1, 4);
//	SeqListPushBack(&s1, 5);
//	SeqListPrint(&s1);
//	SeqListPushFront(&s1, 1);
//	SeqListPushFront(&s1, 2);
//	SeqListPushFront(&s1, 3);
//	SeqListPushFront(&s1, 4);
//	SeqListPushFront(&s1, 5);
//	SeqListPrint(&s1);
//	SeqListPopFront(&s1);
//	SeqListPopFront(&s1);
//	SeqListPrint(&s1);
//	SeqListPopBack(&s1);
//	SeqListPrint(&s1);
//	SeqListDestory(&s1);
//}


int main()
{
	

	/*SeqListTest1();*/
	/*SeqListTest2();*/
	SL s1;
	SeqListInit(&s1);
	int input = 0;
	int x = 0;
	do
	{
		menu();
		printf("请输入一个选项:>");
		scanf("%d", &input);
		switch (input)
		{
		case EXIT: printf("退出程序\n"); break;
		case PushBack: printf("请输入您要尾插的数,以-1结束:");
			scanf("%d",&x);
			while (x != -1)
			{
				SeqListPushBack(&s1, x);
				scanf("%d",&x);
			}
			break;
		case PopBack: SeqListPopBack(&s1); break;
		case PushFront:printf("请输入您要头插的数,以-1结束:");
			scanf("%d", &x);
			while (x != -1)
			{
				SeqListPushFront(&s1, x);
				scanf("%d", &x);
			}
			break;
		case PopFront:SeqListPopFront(&s1); break;
		case print: SeqListPrint(&s1); break;
		default: printf("无此选项,请重新输入\n");
		}
	} while (input);
	SeqListDestory(&s1);
	return 0;
}

数组相关面试题:

1.27. 移除元素 - 力扣(LeetCode) (leetcode-cn.com)

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。

int removeElement(int* nums, int numsSize, int val){
   
   //思路一:以空间换时间
    //循环nums数组,将不是val的值放入tmp数组中去
    // int tmp[100] = {0};
    // int i = 0;
    // int j = 0;
    // for(i = 0;i < numsSize;i++)
    // {
    //     if(nums[i] != val)
    //     {
    //         tmp[j] = nums[i];
    //         j++;
    //     }
    // }
    //  for(i = 0;i < j;i++)
    // {
    //    nums[i] = tmp[i];
    // }
    // return j;
    
    //思路二:使用空间为o(1)
    int res = 0;//用res去找不是val的值,知道找完
    int dest = 0;//将res不是val的值放到dest位置,然后dest++
    while(res < numsSize)
    {
        if(nums[res] != val)
        {
            nums[dest] = nums[res];
            dest++;
        }
        res++;
    }
    return dest;
}

2.26. 删除有序数组中的重复项 - 力扣(LeetCode) (leetcode-cn.com)

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

int removeDuplicates(int* nums, int numsSize)
{
  int ptr = 0;
  int begin = 0;
  //ptr进行寻找,和begin相同,那么++,不同则放入begin处
  while(ptr < numsSize)
  {
      if(nums[ptr] != nums[begin])
      {
          begin++;
          nums[begin] = nums[ptr];
          
      }
      ptr++;
  }
  return begin+1;
}

3.88. 合并两个有序数组 - 力扣(LeetCode) (leetcode-cn.com)

给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{
  //设置2个指针,都是从后往前找
  //将大的放进第三个指针处
  //如果nums2的指针先结束,那么就不用动
  //如果nums1的指针先结束,那么就讲nums2的指针赋值到nums1中 

    int end1 = m - 1;
    int end2 = n - 1;
    int end = m + n -1;

    while(end1 >= 0 && end2 >= 0)//有一个结束了就结束了,然后进行放
    {
            if(nums2[end2] > nums1[end1])
            {   
                nums1[end] = nums2[end2];
                end--;
                end2--;
            }
            else
            {
                nums1[end] = nums1[end1];
                end--;
                end1--;
            }

    }
    if(end1 < 0)
    {
        while(end >= 0)
        {
            nums1[end] = nums2[end2];
            end2--;
            end--;
        }
    }
    
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值