【数据结构】顺序表详解

这篇具有很好参考价值的文章主要介绍了【数据结构】顺序表详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

当我们写完通讯录后,顺序表肯定难不倒你,跟着小张一起来学习顺序表吧!


线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。
【数据结构】顺序表详解,数据结构

【数据结构】顺序表详解,数据结构

顺序表

概念及结构

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

  1. 静态顺序表:使用定长数组存储元素。
    【数据结构】顺序表详解,数据结构
  2. 动态顺序表:使用动态开辟的数组存储。
    【数据结构】顺序表详解,数据结构

接口实现

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

typedef struct pro
{
	int* p;// 指向动态开辟的数组
	int size;// 有效数据个数
	int capcity;// 容量空间的大小

}pro;
void  SeqListInit(pro* ps );//初始化顺序表
void CheckCapacity(pro* ps);//判断是否空间不够,进行扩容
void  SeqListPushBack(pro* ps,int x);//尾插
void  SeqListPushFront(pro* ps, int x);//头插
void SeqListPopBack(pro* ps);//尾删
void  SeqListPopFront(pro* ps);//头删
void  SeqListPrint(pro* ps);//打印顺序表
void SeqListInsert(pro* ps, int pos, int x);//随意插
void SeqListErase(pro* ps, int pos);//随意删
void SeqListFind(pro* ps, int pos);//查找
void SeqListmodify(pro* ps, int x,int y);//修改
void SeqListDestory(pro* ps);//销毁

结构体定义和创建一个结构体变量

typedef struct pro
{
	int* p;// 指向动态开辟的数组
	int size;// 有效数据个数
	int capcity;// 容量空间的大小

}pro;
int main()
{
	pro info;//定义一个结构体变量
}

初始化顺序表

void  SeqListInit(pro* ps )//初始化顺序表
{
	ps->p = NULL;
	ps->size = 0;
	ps->capcity = 0;
	
}

初始化顺序表,有效数据个数为0,容量空间大小为0,还未给数据动态开辟空间,指向动态开辟空间的指针指向空地址

扩容顺序表

void CheckCapacity(pro* ps)//判断是否空间不够,进行扩容
{
	if (ps->size == ps->capcity)
	{
		int newcapcity = ps->capcity == 0 ? 4 : (ps->capcity) * 2;
		int* tmp = (int*)realloc(ps->p, sizeof(int) * newcapcity);
		if (tmp == NULL)
		{
			perror("realloc fail!!");

        }
		ps->p = tmp;
		ps->capcity = newcapcity;

   }


}

什么时候需要扩容顺序表呢??当顺序表刚被初始化,你要进行插入数据时,发现容量空间已经满了,此时必须要扩容空间,当你要插入第一个数据时,在此之前,顺序表没有任何数据,容量空间为0,然后要插入数据的话,也必须扩容。
条件判断如果有效数据个数等于容量大小时,分两种情况,第一种,刚开始的时候,有效数据个数和容量大小都为0的时候,第二种,当要插入数据时,发现此时的有效数据个数和容量大小相等时,且不等于0.对空间进行扩容, newcapcity变量是新的容量大小,当需要扩容的时候,直接新容量为原来的2倍,刚开始,他的容量是0,采用三目运算符,如果容量是0的话,就给四个空间大小,如果不是就开原来容量的2倍。将realloc来的空间的地址存放在tmp指针里面,如果realloc失败就返回空指针,打印错误信息,realloc成功的话就将tmp中存放扩容的地址交给指针p,然后容量大小更新为newcapcity。

尾插

void  SeqListPushBack(pro* ps,int x)//尾插
{
	CheckCapacity(ps);
    ps->p[ps->size] = x;
	ps->size++;}

每次插入都要判断是否需要扩容
【数据结构】顺序表详解,数据结构
然后有效数据+1.

头插

void  SeqListPushFront(pro* ps, int x)//头插
{
	CheckCapacity(ps);
	int end = ps->size - 1;
	while (end>=0)
	{
		ps->p[end + 1] = ps->p[end];
		end--;


    }

	ps->p[0] = x;
	ps->size++;



}

头插一个数据,必须将后面的数据向后面移动,移动的过程中可能超过容量大小,所以在插入时都需要进行扩容判断
【数据结构】顺序表详解,数据结构
如果按这个顺序移动数据当1挪到2的位置的时候,2这个数据就会被覆盖,所以我们必须从后往前面挪
【数据结构】顺序表详解,数据结构
【数据结构】顺序表详解,数据结构当数据挪到后面之后,然后在第一个位置填入x,第一个位置也就是下标为0的位置。
【数据结构】顺序表详解,数据结构

在下标为0的地方填入 插入的数据x,然后ps->size+1;

尾删

void SeqListPopBack(pro* ps)//尾删
{
	assert(ps);
	assert(ps->size > 0);
	ps->size--;

}

尾巴要删除一个数据的话,我们需要将删除的数据改为0吗?如果要删除的数据本来就是0呢?所以我们只需要将ps->size–;因为打印的时候只打印到下标为ps->size-1的位置,打印出来看起来就像 我们删除了这个数据,注意这里用断言是因为在删除的时候ps->size–,当ps->size<0的时候,在添加数据时
ps->p[-1]=x;这个是不合理的,在ps->size<0时,直接报错,第一个断言是为了防止空指针。

头删

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

}

这里的断言和上面是一个道理,然后相比尾删向后挪动数据,头删是往前挪数据,吸取尾删的教训,我们可以直到移动的顺序是
【数据结构】顺序表详解,数据结构
定义一个变量begin=1,首先是要将数据2移动到数据1的位置,对应的操作是
ps->p[begin - 1] = ps->p[begin];然后begin++,依次将数据3挪到数据2的位置,数据4挪到数据3的位置。循环最后一次是将数据5挪到数据4的位置,也就是begin=4,ps->size=5.则循环判断条件为beginsize,循环结束后将
ps->size–;

顺序表的打印

void  SeqListPrint(pro* ps)//打印顺序表
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->p[i]);



	}

}

循环遍历顺序表,将每个数据打印出来

随意插

void SeqListInsert(pro* ps, int pos, int x)//随意插
{
	CheckCapacity(ps);
	assert(pos>=0&&pos<=ps->size);
	int end = ps->size - 1;
	while (end>=pos)
	{
		ps->p[end + 1] = ps->p[end];
		end--;

    }
	ps->p[pos] = x;
	ps->size++;
}

断言是为了检查插入的位置是否合理
【数据结构】顺序表详解,数据结构
当有5个数据时,pos的可能取值如图所示,推广到一般
就是pos>=0&&pos<=ps->size,如果我们想在pos=2的位置插入一个x,我们应该怎么做呢?
1.插入一个x,我们需要将3,4,5向后移动,必须先移动5,定义一个变量end,
【数据结构】顺序表详解,数据结构
end变量的初值给ps->size-1,也就是4,要想将数据5向后挪动,对应的操作是ps->p[end + 1] = ps->p[end];然后end–;循环分别将4,3向后挪动,循环结束后,将数据x插入到pos=2的位置,对应操作为ps->p[pos] = x;然后有效数据大小ps->size++;

随意删

void SeqListErase(pro* ps, int pos)//随意删
{
	int begin = pos;

	assert(pos >= 0 && pos <= ps->size);
	while (begin<ps->size-1)
	{


		ps->p[begin] = ps->p[begin+1];
		begin++;

    }
	ps->size--;
}

断言判断删除的数据的位置是否合理,和随意插的那里一样
【数据结构】顺序表详解,数据结构
如果我们要删除数3,然后数据3后面的数据向前挪动,第一步就是将数据4移动到数据3的位置,定义一个变量begin=pos=2;对应的操作为
ps->p[begin] = ps->p[begin+1];,然后begin++;将数据5移动到最开始数据4的地方。最后一次循环是将数据5移动到数据4的地方,也就是begin最后等于3,ps->size=5,则循环判断条件是begin< ps->size-1,循环结束将ps->size–;

顺序表的查找

void SeqListFind(pro* ps, int pos)//查找
{
	assert(pos >= 0 && pos < ps->size);



	printf("你查找的下标是%d,对应的数据是%d", pos, ps->p[pos]);
}

断言保证查找位置的合理性,因为函数传参pos 刚好是要查找数据的下标,直接打印出来

顺序表的修改

void SeqListmodify(pro* ps, int x,int y)//修改
{
	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->p[i])
		{
			ps->p[i] = y;
		}


  }

}

x为修改前的值,y是修改之后的值,循环遍历顺序表,将顺序表中所有的x都修改成y

顺序表的销毁

void SeqListDestory(pro* ps)//销毁
{
	ps->capcity = 0;
	ps->size = 0;
	free(ps->p);
	ps->p = NULL;





}

销毁一个顺序表,将顺序表的容量置为0,顺序表的有效数据个数置为0,将p指针所指向的动态开辟的内存空间释放了,由于释放了动态开辟的内存空间,所有p指向的空间未初始化,p成为野指针,为了防止野指针,将p置为空指针。文章来源地址https://www.toymoban.com/news/detail-691770.html

整体代码

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct pro
{
	int* p;// 指向动态开辟的数组
	int size;// 有效数据个数
	int capcity;// 容量空间的大小

}pro;
void  SeqListInit(pro* ps )//初始化顺序表
{
	ps->p = NULL;
	ps->size = 0;
	ps->capcity = 0;
	
}
void CheckCapacity(pro* ps)//判断是否空间不够,进行扩容
{
	if (ps->size == ps->capcity)
	{
		int newcapcity = ps->capcity == 0 ? 4 : (ps->capcity) * 2;
		int* tmp = (int*)realloc(ps->p, sizeof(int) * newcapcity);
		if (tmp == NULL)
		{
			perror("realloc fail!!");



		}
		ps->p = tmp;
		ps->capcity = newcapcity;






	}


}
void  SeqListPushBack(pro* ps,int x)//尾插
{
	CheckCapacity(ps);
    ps->p[ps->size] = x;
	ps->size++;



}
void  SeqListPushFront(pro* ps, int x)//头插
{
	CheckCapacity(ps);
	int end = ps->size - 1;
	while (end>=0)
	{
		ps->p[end + 1] = ps->p[end];
		end--;


    }

	ps->p[0] = x;
	ps->size++;



}
void SeqListPopBack(pro* ps)//尾删
{
	assert(ps);
	assert(ps->size > 0);
	ps->size--;

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

}
void  SeqListPrint(pro* ps)//打印顺序表
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->p[i]);



	}

}
void SeqListInsert(pro* ps, int pos, int x)//随意插
{
	CheckCapacity(ps);
	assert(pos>=0&&pos<=ps->size);
	int end = ps->size - 1;
	while (end>=pos)
	{
		ps->p[end + 1] = ps->p[end];
		end--;

    }
	ps->p[pos] = x;
	ps->size++;
}
void SeqListErase(pro* ps, int pos)//随意删
{
	int begin = pos;

	assert(pos >= 0 && pos <= ps->size);
	while (begin<ps->size-1)
	{


		ps->p[begin] = ps->p[begin+1];
		begin++;

    }
	ps->size--;








}
void SeqListFind(pro* ps, int pos)//查找
{
	assert(pos >= 0 && pos < ps->size);



	printf("你查找的下标是%d,对应的数据是%d", pos, ps->p[pos]);
}
void SeqListmodify(pro* ps, int x,int y)//修改
{
	for (int i = 0; i < ps->size; i++)
	{
		if (x == ps->p[i])
		{
			ps->p[i] = y;
		}





	}






}
void SeqListDestory(pro* ps)//销毁
{
	ps->capcity = 0;
	ps->size = 0;
	free(ps->p);
	ps->p = NULL;





}
int main()
{
	pro info;
	SeqListInit(&info);
	printf("尾插:");
	SeqListPushBack(&info, 1);
	SeqListPushBack(&info, 2);
	SeqListPushBack(&info, 3);
	SeqListPushBack(&info, 4);
	SeqListPrint(&info);
	printf("\n");
	printf("头插:");
	SeqListPushFront(&info, 7);
	SeqListPushFront(&info, 6);
	SeqListPushFront(&info, 5);
	SeqListPushFront(&info, 5);
	SeqListPrint(&info);
	printf("\n");
	printf("尾删:");
	SeqListPopBack(&info);
	SeqListPrint(&info);
	printf("\n");
	printf("头删:");
	SeqListPopFront(&info);
	SeqListPrint(&info);
	printf("\n");
	printf("随意插:");
	SeqListInsert(&info, 1, 1);
	SeqListPrint(&info);
	printf("\n");
	printf("随意删:");
	SeqListErase(&info,1,1);
	SeqListPrint(&info);
	printf("\n");
	printf("查找:");
	SeqListFind(&info, 3);
	printf("\n");
	printf("修改:");
	SeqListmodify(&info, 1, 2);
	SeqListPrint(&info);
	printf("\n");
	printf("销毁:");
	SeqListDestory(&info);
    SeqListPrint(&info);
}

到了这里,关于【数据结构】顺序表详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构入门 — 顺序表详解

    数据结构入门 — 顺序表详解 博客主页链接:https://blog.csdn.net/m0_74014525 关注博主,后期持续更新系列文章 文章末尾有源码 *****感谢观看,希望对你有所帮助***** 顺序表是连续存储的 顺序表是一种线性表的数据结构,它的数据元素按照一定次序依次存储在计算机存储器中,使

    2024年02月11日
    浏览(37)
  • 数据结构之顺序表详解

    hello,大家好,今天的内容是关于顺序表的,其实之前也发过文章,但是那个时候水平还是差了一点,有些地方不是很详细,这次会把每个点都讲清楚,也当给自己在复习一遍。 顺序表在本质上就是数组,顺序表是连续的,我们的数组在内存上也是连续存储的,所以我们可以

    2024年02月06日
    浏览(39)
  • 数据结构:详解【顺序表】的实现

    顺序表是用一段 物理地址连续 的存储单元 依次存储数据元素 的线性结构,一般情况下采用数组存储。动态顺序表与数组的本质区别是—— 根据需要动态的开辟空间大小。 动态顺序表的功能一般有如下几个: 初始化顺序表 打印顺序表中的数据 检查顺序表的容量 顺序表头部

    2024年03月14日
    浏览(56)
  • 【数据结构】 顺序表详解!(源码+解析)

    🎥 屿小夏 : 个人主页 🔥个人专栏 : 数据结构解析 🌄 莫道桑榆晚,为霞尚满天! ​ 什么是数据结构?我们为什么要学数据结构?数据结构中的顺序表长什么样子?它是怎么运用? ​ 本期我们将对这些一一讲解,彻底明白数据结构的重要性,以及顺序表是一种什么的数据

    2024年02月06日
    浏览(44)
  • 【数据结构】 顺序表详解!深入理解!

    🎥 屿小夏 : 个人主页 🔥个人专栏 : 数据结构解析 🌄 莫道桑榆晚,为霞尚满天! ​ 什么是数据结构?我们为什么要学数据结构?数据结构中的顺序表长什么样子?它是怎么运用? ​ 本期我们将对这些一一讲解,彻底明白数据结构的重要性,以及顺序表是一种什么的数据

    2024年02月08日
    浏览(42)
  • 数据结构学习分享之顺序表详解

    在前一个章节中我们介绍到, 数据结构(Data Structure)是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元素的集合。 那么具体有哪些结构是我们常常用来存储数据的呢?今天就给大家讲解其中的一个结构: 顺序表, 本篇文章将收录于数据结构学习分享专

    2024年02月05日
    浏览(48)
  • 数据结构 - 2(顺序表10000字详解)

    在集合框架中,List是一个接口,继承自Collection。 Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示: Iterable也是一个接口,Iterable接口表示实现该接口的类是可以逐个元素进行遍历的, 站在数据结构的角度来看,List就是一个线性表,即n个具

    2024年02月08日
    浏览(42)
  • 数据结构(C语言)——顺序表详解

    数据结构是计算机存储和组织数据的方式。常用的数据结构有:数组(Array)、栈(Stack)、队列(Queue)、链表(Linked List)、树(Tree)、图(Graph)、堆(Heap)等;而数据结构又可以通过逻辑结构与物理结构进行分类,逻辑结构是指数据元素之间的逻辑关系,也就是数据元

    2024年04月16日
    浏览(38)
  • 《Java数据结构入门》顺序表详解

     大家好,我是小鱼儿 目录 顺序表介绍: 顺序表的手动实现 顺序表功能接口概览 基本功能的实现 四大功能 一、增加数据  二、删除数据 三、查找数据 四、修改数据  总代码 MyArraysList.java  Test.java 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一

    2023年04月18日
    浏览(33)
  • 【数据结构专栏】动态扩容顺序栈详解

      💌 博客内容:顺序栈的原理详解 😀 作  者:陈大大陈 🚀 个人简介:一个正在努力学技术的准前段,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家:这里是CSDN,我总结知识和写笔记的地方,喜欢的话请三连,有问题请私信 😘 😘 😘 目录 顺序栈的定义 结构体定义

    2023年04月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包