【数据结构】动态顺序表

线性表

    在说顺序表之前我们先来了解一下线性表, 线性表就是n个类型相同的数据元素的有限序列.

    线性表在逻辑上是线性的结构, 可以理解为一条直线, 但是在物理上不一定是连续的, 物理上通常是以数组和链式结构形式存储

    比如: 

顺序表

概念

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

的增删查改

分类

1. 静态顺序表

    使用定长的数组存储, 但是静态的顺序表是存在栈上的, 但是一般情况下栈只有几M的大小, 如果我们开小了不够用, 但是开的很大

可能就没有办法用了, 可能会造成栈溢出, 所以我们并不推荐使用静态的.

2. 动态顺序表

    在堆上开辟空间, 根据我们自己所需要的大小来分配, 相较于静态顺序表更加的灵活一点, 一般情况下使用的都是顺序表 

实现

主要实现 : 增删改查, 大小, 打印, 思路都非常简单, 我都写在注释里了

在这里演示一下增加和删除

增加:

删除:

 

代码

动态顺序表.h
#pragma once
#include <stdio.h>
#include <malloc.h>
#include <assert.h>
#include <stdlib.h>

typedef int Datatype;
typedef struct SeqList
{
	//定义一个动态的数组
	Datatype* _array;
	//大小
	size_t _size;
	//容量
	size_t _capacity;
}SeqList;

//初始化
void SeqListInit(SeqList* s);
//销毁
void SeqListDestory(SeqList* s);
//检查容量
void SeqListCHECK(SeqList* s);
//增删改查

//头插尾插
void SeqListPushBack(SeqList* s, Datatype data);
void SeqListPushFront(SeqList* s, Datatype data);
//任意位置插入
void SeqListInsert(SeqList* s, size_t pos, Datatype data);

//头删尾删
void SeqListPopFront(SeqList* s);
void SeqListPopBack(SeqList* s);
//任意位置删除
void SeqListErase(SeqList* s, size_t pos);
//删除值为所有data的元素
void SeqListRemoveAll(SeqList* s, Datatype data);

//修改
void SeqListModify(SeqList* s, size_t pos, Datatype data);

//查找
void SeqListFind(SeqList* s, Datatype data);

//打印顺序表
void SeqListPrint(SeqList* s);

//打印大小
void SeqListSize(SeqList* s);

//排序
void SeqListBubbleSort(SeqList* s);
Test.c
#include "动态顺序表.h"

//初始化
void SeqListInit(SeqList* s)
{
	assert(s);
	s->_array = NULL;
	s->_capacity = 0;
	s->_size = 0;
}

//销毁
void SeqListDestory(SeqList* s)
{
	assert(s);
	//如果数组不为空
	if (s->_array)
	{
		//先置空再释放, 否则空指针解引用
		s->_array = NULL;
		s->_size = s->_capacity = 0;
		free(s->_array);
	}
}

//增删改查

//头插尾插
void SeqListPushFront(SeqList* s, Datatype data)
{
	assert(s);
	SeqListCHECK(s);
	//头插
	//将所有元素向后挪动一次, 然后修改下标为0的元素, 完了之后size++
	for (size_t i = s->_size; i > 0; i--)
	{
		s->_array[i] = s->_array[i - 1];
	}
	s->_array[0] = data;
	s->_size++;
}
void SeqListPushBack(SeqList* s, Datatype data)
{
	//直接插入, size++
	assert(s);
	SeqListCHECK(s);
	s->_array[s->_size++] = data;
}

//任意位置插入
void SeqListInsert(SeqList* s, size_t pos, Datatype data)
{
	//从pos开始往后的元素同一向后挪动, 在pos处插入data
	assert(s);
	SeqListCHECK(s);
	for (size_t i = s->_size; i >= pos; i--)
	{
		s->_array[i] = s->_array[i - 1];
	}
	s->_array[pos - 1] = data;
	s->_size++;
}

//检查容量
void SeqListCHECK(SeqList* s)
{
	assert(s);
	//如果size等于capacity了肯定就是满了, realloc扩大空间
	if (s->_size == s->_capacity)
	{
		size_t newcapacity = s->_capacity == 0 ? 5 : 2 * s->_capacity;
		//这里注意不要忘记了后面的sizeof(Datatype), 否则开出的只是newcapacity个字节
		//我们其实开辟的是newcapacity个Datatype类型的空间
		s->_array = (Datatype*)realloc(s->_array, newcapacity * sizeof(Datatype));
		s->_capacity = newcapacity;
	}
}

//头删尾删
void SeqListPopFront(SeqList* s)
{
	//直接从第二个元素开始都向前挪一次, 将下标为0的元素覆盖掉, size--就行了
	assert(s);
	for (size_t i = 0; i < s->_size; i++)
	{
		s->_array[i] = s->_array[i + 1];
	}
	s->_size--;
}
void SeqListPopBack(SeqList* s)
{
	//直接size--,最后一个元素就没了
	assert(s);
	s->_size--;
}

//任意位置删除
void SeqListErase(SeqList* s, size_t pos)
{
	assert(s);
	//从pos处往后向前挪动, 是一个覆盖的过程, size--
	for (size_t i = pos - 1; i < s->_size; i++)
	{
		s->_array[i] = s->_array[i + 1];
	}
	s->_size--;
}

//删除值为所有data的元素
void SeqListRemoveAll(SeqList* s, Datatype data)
{
	assert(s);
	size_t index = 0;
	//覆盖法
	for (size_t i = 0; i < s->_size; ++i)
	{
		if (s->_array[i] != data)
			s->_array[index++] = s->_array[i];
	}
	s->_size = index;
}

//二分查找
void SeqListFind(SeqList* s, Datatype data)
{
	assert(s);
	int flag = -1;
	size_t left = 0;
	size_t right = s->_size - 1;
	while (left <= right)
	{
		int mid = left + (right - left) / 2;
		if (s->_array[mid] > data)
			right = mid - 1;
		else if (s->_array[mid] < data)
			left = mid + 1;
		else
		{
			flag = mid;
			break;
		}
	}
	if (flag == -1)
		printf("%d is not exits\n", data);
	else
		printf("%d is exits, number is %d\n", data, flag);
}


//冒泡排序
void SeqListBubbleSort(SeqList* s)
{
	assert(s);
	for (size_t bound = 0; bound < s->_size; ++bound)
	{
		int flag = 0;
		for (size_t i = s->_size - 1; i > bound; --i)
		{
			if (s->_array[i] < s->_array[i - 1])
			{
				flag = 1;
				Datatype ret = s->_array[i];
				s->_array[i] = s->_array[i - 1];
				s->_array[i - 1] = ret;
			}
		}
		//有可能没有排序完已经有序, 直接终止
		if (flag == 0)
			break;
	}
}

//修改
void SeqListModify(SeqList* s, size_t pos, Datatype data)
{
	assert(s);
	s->_array[pos - 1] = data;
}

//打印
void SeqListPrint(SeqList* s)
{
	assert(s);
	for (size_t i = 0; i < s->_size; ++i)
	{
		printf("%d  ", s->_array[i]);
	}
	printf("\n");
}

//返回大小
void SeqListSize(SeqList* s)
{
	assert(s);
	size_t count = 0;
	for (size_t i = 0; i < s->_size; i++)
	{
		count++;
	}
	printf("size is %d\n", count);
}
main.c
#include "动态顺序表.h"

void test()
{
	SeqList s;
	//初始化
	SeqListInit(&s);
	SeqListPushBack(&s, 7);
	SeqListPushBack(&s, 8);
	SeqListPushBack(&s, 9);
	SeqListPushFront(&s, 4);
	SeqListPushFront(&s, 3);
	SeqListPushFront(&s, 0);
	SeqListInsert(&s, 3, 5);
	SeqListInsert(&s, 3, 2);
	SeqListInsert(&s, 3, 6);
	SeqListInsert(&s, 3, 1);
	//排序
	SeqListBubbleSort(&s);
	SeqListPrint(&s);
	//删除
	SeqListErase(&s, 5);
	SeqListPrint(&s);
	//插入两个5, 然后RemoveAll
	SeqListInsert(&s, 5, 5);
	SeqListInsert(&s, 7, 5);
	SeqListPrint(&s);
	SeqListRemoveAll(&s, 5);
	SeqListPrint(&s);
	//查找
	SeqListFind(&s, 7);
	//销毁
	SeqListDestory(&s);
}
int main()
{
	test();
	system("pause");
	return 0;
}

 运行结果

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值