基础数据结构-不定长顺序表

先写头文件:Dsqlist.h

#pragma once

typedef int ELEM_TYPE;
#define INIT_SIZE 10

//不定长顺序表的结构体设计:
typedef struct Dsqlist
{
	ELEM_TYPE *elem;//指针,用来接收malloc返回值
	int length;//当前有效值个数(当前有多少个格子被占用)
	int list_size;//当前总空间个数(当前一共有多少个格子)
}Dsqlist, *PDsqlist;

//不定长顺序表可以实现的操作函数:
//增删改查
//初始化
void Init_Dsqlist(struct Dsqlist * p);//void Init_sqlist(PDsqlist p);

//按位置插入
bool Insert_pos(PDsqlist p, int pos, int val);

//按位置删除
bool Del_pos(PDsqlist p, int pos);

//按值删除
bool Del_val(PDsqlist p, int val);

//获取其有效长度
int Get_length(PDsqlist p);

//扩容    以2倍扩容  
void Inc(PDsqlist p);     

//获取值所在下标(如果数据重复,则返回val第一次出现的位置)
int Search(PDsqlist p, int val);

//判空
bool IsEmpty(PDsqlist p);

//判满
bool IsFull(PDsqlist p);

//清空
void Clear(PDsqlist p);

//销毁
void Destroy(PDsqlist p);

//打印
void Show(PDsqlist p);

Dsqlist.cpp

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include "Dsqlist.h"
/*
顺序表的特点:(插入删除操作较少,随机访问数组中值这个操作较多)
1.逻辑简单,实现简单
2.插入操作时间复杂度O(n),因为需要挪动数据   但是尾插不需要挪动数据(尾插时间复杂度O(1))
3.删除操作时间复杂度O(n),因为需要向前覆盖数据   但是尾删除不需要挪动数据(尾删时间复杂度O(1))
4.随机访问时间复杂O(1),因为顺序表可以通过下标直接访问数组中的元素值

顺序表:数据和数据之间,逻辑相邻,物理也相邻

*/

//不定长顺序表可以实现的操作函数:
//增删改查
//初始化
void Init_Dsqlist(struct Dsqlist * p)//void Init_sqlist(PDsqlist p);
{
	assert(p != NULL);
	if(p == NULL)
		return;

	p->elem = (ELEM_TYPE*)malloc(INIT_SIZE * sizeof(ELEM_TYPE));
	assert(p->elem != NULL);
	if(p->elem == NULL)
		return;

	p->length = 0;
	p->list_size = INIT_SIZE;
}

//按位置插入
bool Insert_pos(PDsqlist p, int pos, int val)
{
	//assert    p
	//assert    pos 
	//判满   扩容   
	if(IsFull(p))
	{
		Inc(p); 
	}
	//此时,肯定p不为NULL, 并且pos位置合法, 并且还用空闲位置让我插入
	
	//4.首先挪动数据,让待插入位置空出来,再将值val放进去即可
	//(插入,挪动数据,从后先前挪)

	for(int i=p->length-1; i>=pos; i--)//i一开始指向最后一个元素下标,最后挪动的数据下标是pos
	{
		p->elem[i+1] = p->elem[i];
	}
	//此时,for循环执行结束  标识着挪动数据完成   现在只需要将插入的值val赋值进去
	p->elem[pos] = val;
	//别忘了 插入操作最后还有一个有效值个数length++
	p->length++;

	return true;
}

//按位置删除
bool Del_pos(PDsqlist p, int pos)
{
	//1.判空  p!=NULL    判断定长顺序表是否存在
	assert(p!=NULL);
	if(p == NULL)
		return false;

	//2.判断删除位置 是否合法
	assert(pos >=0 && pos<p->length);//  删除的时候pos==p->length不合法
	if(pos<0 || pos>=p->length)
		return false;

	//3.判空操作
	if(IsEmpty(p))
		return false;


	//4.将待删除位置后面的有效值,一次向前挪动一位,将删除位置覆盖掉即可
	//(删除,向前覆盖数据,离待删除位置最近的元素先挪动)

	for(int i=pos+1; i<=p->length-1; i++)
	{
		p->elem[i-1] = p->elem[i];
	}
	//此时,for循环执行结束  标识着数据向前覆盖完成   现在只需要将p->length--
	p->length--;

	return true;
}

//按值删除
bool Del_val(PDsqlist p, int val)
{
	//assert p
	//判断val这个值  存不存在
	int index = Search(p, val);
	if(index == -1)
	{
		return false;
	}

	return Del_pos(p, index);
}

//获取其有效长度
int Get_length(PDsqlist p)
{
	//assert
	return p->length;
}

//扩容    以2倍扩容  
void Inc(PDsqlist p)
{
	//assert  p   这个断言需不需要?  不需要
	
	/*ELEM_TYPE* tmp = (ELEM_TYPE*)realloc(p->elem, p->list_size*sizeof(ELEM_TYPE) * 2);
	assert(tmp != NULL);
	if(tmp == NULL)
	{
		printf("realloc error\n");
		return;
	}
	else
	{
		p->elem = tmp;
	}*/

	p->elem = (ELEM_TYPE*)realloc(p->elem, p->list_size*sizeof(ELEM_TYPE) * 2);
	assert(p->elem != NULL);
	if(p->elem == NULL)
	{
		printf("realloc error\n");
		return;
	}
	//p->length;//扩容之后 有效值个数不变
	p->list_size *= 2;//扩容之后  总格子个数需要*2

}

//获取值所在下标(如果数据重复,则返回val第一次出现的位置)
int Search(PDsqlist p, int val)
{
	//assert
	for(int i=0; i<p->length; i++)
	{
		if(p->elem[i] == val)
		{
			return i;
		}
	}
	return -1;
}

//判空
bool IsEmpty(PDsqlist p)
{
	//assert
	return p->length == 0;
}
//判满
bool IsFull(PDsqlist p)
{
	//assert
	return p->length == p->list_size;
}

//清空
void Clear(PDsqlist p)
{
	//assert
	p->length = 0;
}

//销毁  主要处理内存泄露
void Destroy(PDsqlist p)
{
	//assert
	free(p->elem);
}

//打印
void Show(PDsqlist p)
{
	//assert
	for(int i=0; i<p->length; i++)
	{
		printf("%d ", p->elem[i]);
	}
	printf("\n");
}

主函数:

#include <stdio.h>
#include "assert.h"
#include <stdlib.h>
#include <vld.h>
//#include "sqlist.h"
#include "Dsqlist.h"

//不定长顺序表测试用例
int main()
{
	struct Dsqlist head;
	Init_Dsqlist(&head);
	printf("maxsize: %d\n", head.list_size);
	printf("length = %d\n", Get_length(&head));
	
	for(int i=0; i<10; i++)
	{
		Insert_pos(&head, i, i+1);
	}
	Insert_pos(&head, 0, 100);
	Insert_pos(&head, head.length, 200);
	printf("maxsize: %d\n", head.list_size);
	printf("length = %d\n", Get_length(&head));
	Show(&head);

	Del_pos(&head, 3);
	Show(&head);
	Del_val(&head, 9);
	Show(&head);

	printf("%d\n", Search(&head, 5));
	printf("%d\n", Search(&head, 300));

	Clear(&head);
	printf("length = %d\n", Get_length(&head));
	Show(&head);

	Destroy(&head);

	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值