自学内容网 自学内容网

顺序表及其代码实现

前言

顺序表一般不会用来单独存储数据,但自身的优势,很多时候不得不使用顺序表。

1.顺序表

1.1 顺序表介绍

顺序表是物理结构连续的线性表,支持随机存取(底层是数组),存储密度大(只需存储数据元素,与链表相比,无需存储额外的指针)。缺点是,由于物理结构的连续,插入、删除要移动大量元素,时间复杂度为O(n),效率低下。
顺序表的组成如下,顺序表分为静态顺序表与动态顺序表。静态顺序表申请内存后不能更改,存在的问题是由于不确定需要的内存大小,如果开辟的内存块比较小,不够用;开辟过大,造成浪费。
动态顺序表可以在内存不够的时候调整顺序表的大小,注意,每次增加开辟的内存空间可以是原来内存的1~2倍,如果每次增加一个元素都要调整空间大小,效率太低。
在这里插入图片描述

1.2 顺序表基本操作代码实现

SeqList.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//静态顺序表
//typedef int SLDataType;
//#define N 100000
//
//struct SeqList
//{
//SLDataType a[N];
//int size;
//};

//动态顺序表
typedef int SLDataType;
#define INIT_CAPACITY 4
typedef struct SeqList
{
SLDataType* a;
int size;
int capacity;
}SL;

//增删查改
void SLInit(SL* ps);
void SLDestroy(SL* ps);
void SLPrint(SL* ps);
void SLPrint(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);
void SLCheckCapacity(SL* ps);
int SLFind(SL* ps,SLDataType x);

SeqList.c

#include "SeqList.h"
void SLInit(SL* ps)
{
assert(ps);
ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);
if (ps->a == NULL)
{
perror("malloc failed");
return;
}
ps->size = 0;
ps->capacity = INIT_CAPACITY;
}
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 SLPushBack(SL* ps, SLDataType x)
{
/*SLCheckCapacity(ps);
ps->a[ps->size++] = x;*/
SLInsert(ps, ps->size, x);
}
void SLPopBack(SL* ps)
{
//assert(ps);
//assert(ps->size > 0);
//if (ps->size == 0)
//return;
ps->a[--ps->size] = 0;
//ps->size--;
SLErase(ps, ps->size - 1);
}
void SLCheckCapacity(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * 2 * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc failed");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
}
void SLPushFront(SL* ps, SLDataType x)
{
/*SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
end--;
}
ps->a[0] = x;
ps->size++;*/
SLInsert(ps, 0, x);
}
void SLPopFront(SL* ps)
{
/*assert(ps);
assert(ps->size > 0);
int begin = 1;
while (begin < ps->size)
ps->a[begin - 1] = ps->a[begin++];
ps->size--;*/
SLErase(ps, 0);
}
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
int end = ps->size - 1;
while (end >= pos)
ps->a[end + 1] = ps->a[end--];
ps->a[pos] = x;
ps->size++;
}
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
int begin = pos + 1;
while (begin<ps->size)
ps->a[begin-1] = ps->a[begin++];
ps->size--;
}
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
return i;
}
return -1;
}

Test.c

#include "SeqList.h"
void TestSeqList1()
{
SL s;
SLInit(&s);
SLPushBack(&s, 1);
SLPushBack(&s, 2);
SLPushBack(&s, 3);
SLPushBack(&s, 4);
SLPushBack(&s, 5);
SLPushBack(&s, 6);
SLPushBack(&s, 7);
SLPushBack(&s, 8);
SLPushBack(&s, 9);
SLPrint(&s);

SLPopBack(&s);
SLPopBack(&s);
SLPrint(&s);

SLPopBack(&s);
SLPopBack(&s);
SLPopBack(&s);
SLPopBack(&s);
SLPopBack(&s);
SLPopBack(&s);
SLPopBack(&s);
SLPrint(&s);

SLPopBack(&s);

SLPushBack(&s, 10);
SLPushBack(&s, 20);
SLPrint(&s);

SLDestroy(&s);
}
void TestSeqList2()
{
SL s;
SLInit(&s);
for (int i = 0; i < 10; i++)
SLPushFront(&s, i);
SLPrint(&s);

SLPopFront(&s);
SLPopFront(&s);
SLPrint(&s);

SLInsert(&s, 2, 40);
SLPrint(&s);

SLInsert(&s, 8, 30);
SLPrint(&s);

SLErase(&s, 4);
SLPrint(&s);

printf("%d\n", SLFind(&s, 40));
}
int main()
{
TestSeqList2();
/*void* ptr1 = malloc(5);
printf("%p\n", ptr1);
void* ptr2 = malloc(6);
printf("%p\n", ptr2);*/
return 0;
}

//顺序表可以结合菜单进行操作,但要保证函数代码实现没有问题,否则在菜单中难以调试
//void menu()
//{
//printf("****************************************\n");
//printf("******    1.尾插数据 2.尾删数据   ******\n");
//printf("******    7.打印数据 0.退出程序   ******\n");
//printf("****************************************\n");
//}
//int main()
//{
//SL s;
//SLInit(&s);
//int option = -1;
//while (option != 0)
//{
//menu();
//scanf("%d", &option);
//switch (option)
//{
//case 1:
//printf("请依次输入要尾插的数据,以-1结束>:");
//int x = 0;
//while (x != -1)
//{
//scanf("%d", &x);
//SLPushBack(&s, x);
//}
//break;
//case 7:
//SLPrint(&s);
//break;
//default:
//break;
//} 
//}
//return 0;
//}

总结

顺序表以及后续链表的学习都是对代码能力的锻炼,学习数据结构都是这个思路,逻辑结构、物理结构即基本操作实现。


原文地址:https://blog.csdn.net/m0_74328241/article/details/142527178

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!