C++_数据结构学习—顺序表

std::vector 在 C++ 标准库中的本质可以理解为一种动态顺序表。它是一种能够自动调整大小的数组,会在需要的时候自动分配更大的内存块,从而实现动态扩展和收缩。它在内存中连续存储元素,就像传统的顺序表一样,但它能够动态管理内存,使得插入、删除和访问元素变得更加高效和方便。

vector的C++接口如下:

#include <iostream>
#include <vector>
using namespace std;

// vector
// vector数据结构和数组非常相似,也称为单端数组
// vector与数组的不同之处在于,数组是静态空间,而vector可以动态扩展

void printVector(vector<int>& v)
{
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << *it << " ";
	}
	cout << endl;
}

// 1、vector构造
void test_1()
{
	vector<int>v1; //默认构造,无参数
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	// 通过区间方式进行构造
	vector<int> v2(v1.begin(), v1.end());
	printVector(v2);

	// n个elem方式构造
	vector<int> v3(10, 50); // 构造10个50的元素
	printVector(v3);

	// 拷贝构造(较为常用)
	vector<int> v4(v3);
	printVector(v4);
}

//2、vector赋值
void test_2()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);

	// 赋值 operator = 
	vector<int> v2;
	v2 = v1;
	printVector(v2);

	// assign
	vector<int> v3;
	v3.assign(v1.begin(), v1.end());

	// n个elem的方式
	vector<int>v4;
	v4.assign(10, 100);
	printVector(v4);
}

// 3、vector容量和大小
void test_3()
{
	vector<int> v1;
	bool s;
	int capacity,size;
	for (int i = 0; i < 10; i++)
	{
		cout << "v1是否为空:" <<(s = v1.empty()) << endl;
		v1.push_back(i);
		cout << "v1的容量为:" << (capacity = v1.capacity()) << endl; 
		cout << "v1的大小:" << (size = v1.size()) << endl;
	}
}

// 4、vector的插入和删除
void test_4()
{
	vector<int> v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i); //尾插
	}
	printVector(v1);
	v1.pop_back(); //尾删
	v1.pop_back();
	printVector(v1);

	v1.insert(v1.begin(), 100); //头插
	printVector(v1);

	v1.insert(v1.begin(), 4, 200); //头插
	printVector(v1);

	v1.erase(v1.begin()); //删除
	printVector(v1);

	v1.erase(v1.begin(), v1.end()); //清空
	v1.clear(); //清空
}

//5、vector数据存取:[ ] 和 at
void test_5()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	// 利用[ ]方式访问数组元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1[i] << " ";
	}
	cout << endl;

	//利用at的方式访问元素
	for (int i = 0; i < v1.size(); i++)
	{
		cout << v1.at(i) << " ";
	}
	cout << endl;

	cout << "第一个元素:" << v1.front() << endl; // 返回第一个元素
	cout << "最后个元素:" << v1.back() << endl; // 返回最后一个元素
}

// 6、vector互换容器
void test_6()
{
	vector<int>v1;
	for (int i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
	printVector(v1);
	vector<int> v2;
	for (int i = 10; i >= 0; i--)
	{
		v2.push_back(i);
	}
	printVector(v2);
	v1.swap(v2); //v1和v2两个容器互换
	printVector(v1);
	printVector(v2);
}

// 7、reserve预留空间,容器预留len个元素长度,预留位置不初始化,元素不可访问
void test_7()
{
	vector<int> v;
	//利用reserve预留空间
	v.reserve(10000);

	int* p = NULL;
	int num = 0;
	for (int i = 0; i < 10000; i++)
	{
		v.push_back(i);
		if (p != &v[0])
		{
			p = &v[0];
			num++;
		}
	}
	cout << "num = " << num << endl;
}

int main()
{
	//test_1();
	//test_2();
	//test_3();
	//test_4();
	//test_5();
	//test_6();
	test_7();
	return 0;
}

声明文件

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

//静态顺序表 --不太实用
// N小了不够用 N大了浪费空间
#define N 10
typedef int SLDataType;

//动态顺序表
typedef struct SeqList
{
	SLDataType* a;
	int size; //记录存储多少个有效数据
	int capacity; //空间容量大小
}SL;

void SLInit(SL *ps);
void Destory(SL* ps);
void SLPushBack(SL *ps, int x);  //尾插
void SLPopBack(SL *ps); //尾删
void SLPrint(SL* ps); //打印顺序表中的元素

void SLCheckCapacity(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, int begin); //查找顺序表中元素

顺序表增删查改,功能实现:

#include "SeqList.h"

void SLInit(SL *ps)
{
	ps->a = NULL;
	ps->capacity = 0;
	ps->size = 0;
}

void Destory(SL* ps) //销毁顺序表
{
	if (ps->a != NULL)
	{
		free(ps->a);
		ps->a = NULL;
		ps->capacity = 0;
		ps->size = 0;
	}
}
void SLPrint(SL* ps) //打印顺序表中的元素
{
	for (int i = 0; i < ps->size; i++)
	{
		printf("%d ", ps->a[i]);
	}
	printf("\n"); //换行
}

void SLPushBack(SL* ps, int x)  //尾插
{
	if (ps->capacity == ps->size) //考虑扩容情况
	{
		int newCapacity = ps->capacity  ==  0 ? 4 : ps->capacity * 2;
		SLDataType *tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity); //使用realloc在原有空间上进行扩容
		if (tmp == NULL) //这里要对扩容后的情况进行验证,防止扩容失败
		{
			perror("realloc fail.....");
			exit(-1);
		}
		ps->a = tmp; //将临时的指针tmp指向a
		ps->capacity = newCapacity; // 扩容后的新空间
	}
	ps->a[ps->size] = x; 
	ps->size += 1;
}

void SLPopBack(SL* ps) //尾删
{
		//ps->a[ps->size - 1] = 0; //这一步不必要
	//if (ps->size == 0) //如果size为0,证明没有元素存在了
	//{
	//	return;
	//}
	assert(ps->size > 0); //这里检查方式与STL相同
	ps->size --; 
}

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

	if (ps->capacity == ps->size) //考虑扩容情况
	{
		int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
		SLDataType* tmp = (SLDataType*)realloc(ps->a, sizeof(SLDataType) * newCapacity); //使用realloc在原有空间上进行扩容
		if (tmp == NULL) //这里要对扩容后的情况进行验证,防止扩容失败
		{
			perror("realloc fail.....");
			exit(-1);
		}
		ps->a = tmp; //将临时的指针tmp指向a
		ps->capacity = newCapacity; // 扩容后的新空间
	}
}

	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++;
}


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

	void SLInsert(SL* ps, int pos, SLDataType x) // 中间插入
	{
		assert(ps);
		assert(pos >= 0);
		assert(pos <= ps->size);
		 
		SLCheckCapacity(ps); //检查容量

		int end = ps->size - 1;
		while (end >= pos)
		{
			ps->a[end + 1] = ps->a[end]; //将前面一个数往后面挪动,从后往前挪动
			end--;
		}
		ps->a[pos] = x; //将要插入的数据放进去
	}

	void SLErase(SL* ps, int pos) //中间删除
	{
		assert(ps);
		assert(ps->size > 0);
		assert(pos < ps->size - 1);

		int begin = pos+1;
		while (begin < ps->size)
		{
			ps->a[begin - 1] = ps->a[begin];
			begin++;
		}
		ps->size--; //容量减1
	}

	int SLFind(SL* ps, SLDataType x, int begin) //查找顺序表中元素
	{
		assert(ps);
		
		for (int i = begin; i < ps->size; i++)
		{
			if (ps->a[i] == x) //如果循序表中存在这个元素,返回该元素的位置
			{
				return i;
			}
		}
		return -1; //没有找到

	}

测试函数:

#include "SeqList.h"


void TestSeqList()
{
	SL s1;
	SLInit(&s1);
	SLPushBack(&s1, 1);
	SLPushBack(&s1, 2);
	SLPushBack(&s1, 3);
	SLPushBack(&s1, 4); //尾插
	SLPopBack(&s1); //尾删
	SLPushFront(&s1, 6);
	SLPushFront(&s1, 6);
	SLPushFront(&s1, 6);

	SLInsert(&s1, 2, 40); //在第3个位置插入4
	SLInsert(&s1, 0, 400); //在第3个位置插入4

	SLPrint(&s1);

	int pos = SLFind(&s1, 40, 0); 
	printf("该元素的位置为:%d\n", pos);
	if (pos != -1)
	{
		SLErase(&s1, pos);
	}

	SLPrint(&s1);
	Destory(&s1); //销毁顺序表
}

int main()
{
	TestSeqList();

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值