【数据结构|C语言版】顺序表

  • 前言
  • [1. 初步认识数据结构](#1. 初步认识数据结构)
  • [2. 线性表](#2. 线性表)
  • [3. 顺序表](#3. 顺序表)
    • [3.1 顺序表的概念](#3.1 顺序表的概念)
    • [3.1 顺序表的分类](#3.1 顺序表的分类)
    • [3.2 动态顺序表的实现](#3.2 动态顺序表的实现)
  • 结语

前言

各位小伙伴大家好!小编来给大家讲解一下数据结构中顺序表的相关知识。

1. 初步认识数据结构

【概念】数据结构是计算机存储、组织数据的⽅式。

  • 数据结构是指相互之间存在⼀种或多种特定关系的数据元素的集合
  • 数据结构反映数据的内部构成,即数据由那部分构成,以什么⽅式构成,以及数据元素之间呈现的结构
  • 数据结构能够存储数据(如顺序表、链表等结构)
  • 数据结构存储的数据能够方便查找
  • 数组是最基础的数据结构

2. 线性表

【概念】零个或多个数据元素的有限序列。

【分类】

【补充】

3. 顺序表

3.1 顺序表的概念

【概念】用一组地址连续的存储单元依次存储线性表的数据元素,这种存储结构的线性表称为顺序表。

【特点】逻辑上相邻的数据元素,物理次序也是相邻的。

3.1 顺序表的分类

【分类】

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

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

3.2 动态顺序表的实现

c 复制代码
#define INIT_CAPACITY 4 
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); 
//指定位置之前插⼊/删除数据 
void SLInsert(SL* ps, int pos, SLDataType x);
void SLErase(SL* ps,int pos);
int SLFind(SL* ps, SLDataType x);

【Seqlist.h】

c 复制代码
#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<Windows.h>
typedef int SLDataType;

// sequence list
typedef struct SeqList
{
	SLDataType* a;
	int size;      // 有效数据
	int capacity;  // 空间容量
}SL;

void SLInit(SL* psl);//初始化顺序表
void SLDestroy(SL* psl);//摧毁顺序表

void SLPrint(SL* psl);//打印顺序表
void SLCheckCapacity(SL* psl);//检测顺序表的容量

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

// 任意下标位置的插入删除
void SLInsert(SL* psl, int pos, SLDataType x);//任意下标插
void SLErase(SL* psl, int pos);//任意下标删

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

【Seqlist.c】

c 复制代码
#include"seqlist.h"
#include <string.h>
void SLInit(SL* psl)
{
	assert(psl);

	psl->a = NULL;
	psl->size = 0;
	psl->capacity = 0;
}

void SLDestroy(SL* psl)
{
	assert(psl);

	if (psl->a != NULL)
	{
		free(psl->a);
		psl->a = NULL;
		psl->size = 0;
		psl->capacity = 0;
	}
}

void SLPrint(SL* psl)
{
	assert(psl);

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

void SLCheckCapacity(SL* psl)
{
	assert(psl);

	if (psl->size == psl->capacity)
	{
		int newCapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(psl->a, sizeof(SLDataType) * newCapacity);
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		psl->a = tmp;
		psl->capacity = newCapacity;
	}
}

void SLPushBack(SL* psl, SLDataType x)
{
	assert(psl);

	SLCheckCapacity(psl);

	psl->a[psl->size] = x;
	psl->size++;
}

void SLPushFront(SL* psl, SLDataType x)
{
	assert(psl);

	SLCheckCapacity(psl);

	// 挪动数据
	int end = psl->size - 1;
	while (end >= 0)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}

	psl->a[0] = x;
	psl->size++;
}

void SLPopBack(SL* psl)
{
	assert(psl);

	// 空
	// 温柔的检查
	/*if (psl->size == 0)
	{
		return;
	}*/

	// 暴力检查
	assert(psl->size > 0);

	//psl->a[psl->size - 1] = -1;
	psl->size--;
}

void SLPopFront(SL* psl)
{
	assert(psl);

	// 暴力检查
	assert(psl->size > 0);

	int begin = 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		++begin;
	}

	psl->size--;
}

// 注意pos是下标
// size是数据个数,看做下标的话,他是最后一个数据的下一个位置
void SLInsert(SL* psl, int pos, SLDataType x)
{
	assert(psl);
	assert(pos >= 0 && pos <= psl->size);

	SLCheckCapacity(psl);

	// 挪动数据
	int end = psl->size - 1;
	while (end >= pos)
	{
		psl->a[end + 1] = psl->a[end];
		--end;
	}

	psl->a[pos] = x;
	psl->size++;
}

void SLErase(SL* psl, int pos)
{
	assert(psl);
	assert(pos >= 0 && pos < psl->size);

	// 挪动覆盖
	int begin = pos + 1;
	while (begin < psl->size)
	{
		psl->a[begin - 1] = psl->a[begin];
		++begin;
	}

	psl->size--;
}

int SLFind(SL* psl, SLDataType x)
{
	assert(psl);

	for (int i = 0; i < psl->size; i++)
	{
		if (psl->a[i] == x)
		{
			return i;
		}
	}

	return -1;
}

void SLclear(SL* psl, SLDataType x)
{
	psl->size = 0;
	memset(psl->a, 0, sizeof(psl->a));
	printf("顺序表已清空!!!\n");
	Sleep(1500);
}

【test.c】

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include "seqlist.h"
void TestSL1()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPushBack(&sl, 6);
	SLPushBack(&sl, 7);
	SLPushBack(&sl, 8);
	SLPushBack(&sl, 9);
	SLPrint(&sl);

	SLPushFront(&sl, 10);
	SLPushFront(&sl, 20);
	SLPushFront(&sl, 30);
	SLPushFront(&sl, 40);
	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSL2()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPrint(&sl);

	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPopBack(&sl);
	SLPrint(&sl);

	//SLPopBack(&sl);
	//SLPrint(&sl);

	SLPushFront(&sl, 10);
	SLPushFront(&sl, 20);
	SLPushFront(&sl, 30);
	SLPushFront(&sl, 40);
	SLPrint(&sl);

	SLDestroy(&sl);
}

// 多画图
// 写一个函数,编译一个 测试一个 -> 一步一个脚印
void TestSL3()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	SLPopFront(&sl);
	SLPrint(&sl);

	//SLPopFront(&sl);
	//SLPrint(&sl);
}

void TestSL4()
{
	//SL* ptr = NULL;
	//SLInit(ptr);

	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLInsert(&sl, 2, 20);
	SLPrint(&sl);

	SLInsert(&sl, 6, 20);
	SLPrint(&sl);

	SLInsert(&sl, 0, 20);
	SLPrint(&sl);

	SLInsert(&sl, 10, 20);
	SLPrint(&sl);

	SLDestroy(&sl);
}

void TestSL5()
{
	SL sl;
	SLInit(&sl);
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(&sl, 5);
	SLPrint(&sl);

	SLErase(&sl, 3);
	SLPrint(&sl);

	SLErase(&sl, 3);
	SLPrint(&sl);

	//SLErase(&sl, 3);
	//SLPrint(&sl);
}

void menu()
{
	printf("********************************************\n");
	printf("********************************************\n");
	printf("********1、尾插数据  2、尾删数据************\n");
	printf("********3、头插数据  4、头删数据************\n");
	printf("**5、任意位置插入数据  6、任意位置删除数据**\n");
	printf("********7、查找数据  8、退出顺序表**********\n");
	printf("******** 9、打印顺序表 ********************\n");
	printf("********************************************\n");
	printf("********************************************\n");
}

int main()
{
	/*void TestSL4();
	void TestSL3();
	void TestSL2();
	void TestSL1();*/
	SL s;
	SLInit(&s);

	int option = 0;
	do
	{
		menu();
		printf("请输入你的选择:>");
		scanf("%d", &option);

		if (option == 1)
		{
			printf("请依次输入你的要尾插数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPushBack(&s, x);
			}
		}

		else if (option == 2)
		{
			printf("请输入要尾删数据的个数:");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				SLPopBack(&s);
			}
		}

		else if (option == 3)
		{
			printf("请依次输入你的要头插数据个数和数据:>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				scanf("%d", &x);
				SLPushFront(&s, x);
			}
		}

		else if (option == 4)
		{
			printf("请输入要头删数据的个数:");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				SLPopFront(&s);
			}
		}

		else if (option == 5)
		{
			printf("请先输入你的要任意插入的个数,在输入下标(下标第一个从0开始哦),在输入这个位置的数据(推荐一个一个加,不然你的下标顺序会不好判断哦!):>");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int x = 0;
				int pos = 0;
				scanf("%d %d", &pos, &x);
				SLInsert(&s, pos, x);
			}
		}

		else if (option == 6)
		{
			printf("请输入要删除数据的个数和下标:");
			int n = 0;
			scanf("%d", &n);
			for (int i = 0; i < n; i++)
			{
				int pos = 0;
				scanf("%d", &pos);
				SLErase(&s, pos);
			}
		}

		else if (option == 7)
		{
			printf("请输入要查找的的元素(一个):");
			int num = 0;
			scanf("%d", &num);
			int pos = SLFind(&s, num);
			printf("该元素的下标为:");
			printf("%d", pos);
		}

		else if (option == 8)
		{
			break;
		}

		else if (option == 9)
		{
			printf("顺序表已打印,如下:\n");
			SLPrint(&s);
			Sleep(1500);
		}

		else
		{
			printf("无此选项,请重新输入\n");
		}

	} while (option != 0);

	SLDestroy(&s);

	return 0;
}

结语

以上就是小编对顺序表的一些初步认识。

如果觉得小编讲的还可以,还请一键三连。互三必回!

持续更新中~!

相关推荐
XuanRanDev14 分钟前
【每日一题】LeetCode - 三数之和
数据结构·算法·leetcode·1024程序员节
代码猪猪傻瓜coding16 分钟前
力扣1 两数之和
数据结构·算法·leetcode
EricWang13581 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??1 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
南宫生2 小时前
贪心算法习题其三【力扣】【算法学习day.20】
java·数据结构·学习·算法·leetcode·贪心算法
希言JY2 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若2 小时前
C语言比较两个字符串是否相同
c语言
weixin_432702262 小时前
代码随想录算法训练营第五十五天|图论理论基础
数据结构·python·算法·深度优先·图论
passer__jw7673 小时前
【LeetCode】【算法】283. 移动零
数据结构·算法·leetcode
TeYiToKu4 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm