数据结构“顺序表”

✍前言:
        今天让我们来一起看一下最简单的数据结构--顺序表,虽然说我们大家都叫他顺序表,但是他实际上大家可以理解为一个数组。

线性表 

        线性表的意思就是在逻辑上是一个线性的结构,比如说顺序表,链表,字符串,栈,队列这些结构。 

        这些结构再逻辑上他就是一条直线,但是要注意的是他们有些在物理地址上并不一定是连续的。

 顺序表

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

顺序表又分为:

        1.静态顺序表,平时一般都不使用静态的顺序表,因为他的数组大小是固定的,使用场景比较少,用途比较局限。

        2.动态顺序表,我们主要使用的就是动态顺序表,他的大小是可以根据使用场景变大,可以动态增长。

 接口实现

        顺序表是一个结构体,内部有很多的接口可以让使用者更加方便的使用顺序表结构,下面来看一下各个接口的模拟实现

        结构体成员

    T* _a;
	size_t _size;
	size_t _capacity;

        初始化,也就是实现构造函数

SeqList()
		:_a(nullptr)
		,_size(0)
		,_capacity(0)
	{
	}

        尾部插入数据+尾部删除数据

	void push_back(const T& s)
	{
		reserve(_size + 1);
		_a[_size] = s;
		_size++;
	}
	void pop_back()
	{
		if (_size)
		{
			_size--;
		}
	}

        需要注意的是在插入数据的时候要注意是否扩容,删除的时候直接让个数减减就可以。  

        扩容

void reserve(size_t n)
	{
		if (n > _capacity)
		{
			_capacity = _capacity == 0 ? 4 : _capacity * 2;
			T* tmp=new T[_capacity];
			memcpy(tmp, _a, _size*4);
			delete _a;
			_a = tmp;
		}
	}

        需要注意的是扩容的时候会进行一个判断,如果插入的数据并没有大于容量那么我们就不需要扩容了,在申请空间的时候我们需要把原来的数据拷贝到增大后的空间。

        头部插入数据+头部删除数据

	void push_front(const T& s)
	{
		reserve(_size + 1);
		int end = _size;
		while (end>=1)
		{
			_a[end] = _a[end - 1];
			end--;
		}
		_a[0] = s;
		_size++;
	}
	void pop_front()
	{
		if (_size)
		{
			int begin = 0;
			while (begin<=_size-1)
			{
				_a[begin] = _a[begin + 1];
				begin++;
			}
			_size--;
		}
	}

         这里需要注意的是不管是插入还是删除都采用覆盖的方式,所以头部插入删除的效率都不高。

        查找与打印

void Print()
	{
		for (int i = 0; i < _size; i++)
		{
			cout << _a[i] << " ";
		}
	}
	int Find(const T& t)
	{
		for (int i = 0; i < _size; i++)
		{
			if (_a[i] == t)
			{
				return i;
			}
		}
		return -1;
	}

         指定位置的插入和删除

	void Inerst(size_t pos,const T& t)
	{
		assert(pos <= _size);
		reserve(_size + 1);
		int end = _size;
		while (end > pos)
		{
			_a[end] = _a[end - 1];
			end--;
		}
		_a[pos] = t;
		_size++;
	}
	void Erase(size_t pos)
	{
		assert(pos < _size);
		while (pos < _size-1)
		{
			_a[pos] = _a[pos + 1];
			pos++;
		}
		_size--;
	}

需要注意的是插入和删除的时候也是需要挪动数据的。

 完整代码

         SeqList.h

#pragma once
#include <iostream>
#include <string.h>
#include <assert.h>
using namespace std;

template <class T>
class SeqList
{
public:
	SeqList()
		:_a(nullptr)
		,_size(0)
		,_capacity(0)
	{

	}
	void reserve(size_t n)
	{
		if (n > _capacity)
		{
			_capacity = _capacity == 0 ? 4 : _capacity * 2;
			T* tmp=new T[_capacity];
			memcpy(tmp, _a, _size*4);
			delete _a;
			_a = tmp;

		}
	}
	void push_back(const T& s)
	{
		reserve(_size + 1);
		_a[_size] = s;
		_size++;
	}
	void pop_back()
	{
		if (_size)
		{
			_size--;
		}
	}
	void push_front(const T& s)
	{
		reserve(_size + 1);
		int end = _size;
		while (end>=1)
		{
			_a[end] = _a[end - 1];
			end--;
		}
		_a[0] = s;
		_size++;
	}
	void pop_front()
	{
		if (_size)
		{
			int begin = 0;
			while (begin<=_size-1)
			{
				_a[begin] = _a[begin + 1];
				begin++;
			}
			_size--;
		}
	}
	void Print()
	{
		for (int i = 0; i < _size; i++)
		{
			cout << _a[i] << " ";
		}
	}
	int Find(const T& t)
	{
		for (int i = 0; i < _size; i++)
		{
			if (_a[i] == t)
			{
				return i;
			}
		}
		return -1;
	}
	void Inerst(size_t pos,const T& t)
	{
		assert(pos <= _size);
		reserve(_size + 1);
		int end = _size;
		while (end > pos)
		{
			_a[end] = _a[end - 1];
			end--;
		}
		_a[pos] = t;
		_size++;
	}
	void Erase(size_t pos)
	{
		assert(pos < _size);
		while (pos < _size-1)
		{
			_a[pos] = _a[pos + 1];
			pos++;
		}
		_size--;
	}
private:
	T* _a;
	size_t _size;
	size_t _capacity;
};


test.c

#include "SeqList.h"

int main()
{
	SeqList<int> s;
	s.push_back(1);
	s.push_back(2);
	s.push_back(3);
	s.push_back(4);
	s.push_back(5);
	s.pop_back();
	s.push_front(0);
	s.push_front(10);
	s.pop_front();
	s.pop_front();
	s.Inerst(0, 11);
	s.Erase(5);
	s.Print();
	return 0;
}

 以上就是全部代码,还有很多需要优化的地方,我之后也会继续改良,如有错误和不足的地方。欢迎大家指正,完结撒花  

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值