数据结构记录

第一次学习数据结构,具体学习内容为顺序表。

顺序表是顺序存储结构的线性表。

1.class.h 文件---创建顺序表ADT

这里我使用的是动态指针的方式定义顺序表SeqList:

//顺序表第二种定义-----------动态分配:指针
#define InitSize 10
typedef struct {
	int* data;     //指针
	int maxsize;   //顺序表的最大容量
	int length;    //顺序表的当前长度
}SeqList;          //顺序表的数据元素类型

2.first.c 文件,实现顺序表的插入删除操作

初始化顺序表

#include<stdio.h>
#include"class.h"
#include<stdlib.h>
//指针的方式初始化顺序表

void InitList(SeqList*L) {
	L->data = (int*)malloc(InitSize * sizeof(int));
	L->length = 0;
	L->maxsize = InitSize;
}

class.h为自定义的头文件,这里引用需要双引号。初始化函数InitList。初始化顺序表的长度和最大存储空间。

L->data = (int*)malloc(InitSize * sizeof(int));

上面这句是核心代码,malloc实现动态的申请一片连续的内存空间。malloc执行完成后会return指向这一整片内存空间开始地址的指针。

1.(int*)将malloc函数返回的指针强制转换为我所定义的数据元素的类型指针,这里我定义的是int型指针,赋给L->data这个指针变量,这个指针变量就回指向这片内存空间的起始地址。

2.(sizeof(int)*InitSize)  malloc函数需要申请多大的内存空间?int类型所占的大小为4个字节,乘以顺序表初始长度--->存放10个Int型变量所需要的内存空间。

增加动态数组的长度:

void IncreaseSize(SeqList* L, int len) {      //增加动态数组的长度
	int* p = L->data;
	L->data = (int*)malloc((L->maxsize + len) * sizeof(int));
	for (int i = 0; i < L->length; i++)
	{
		L->data[i] = p[i];           // 将数据复制到新的区域
	}
	L->maxsize = L->maxsize + len;       //顺序表最大长度增加len
	free(p);
}                                     //释放原来的内存空间
  • 顺序表的算法操作

顺序表的插入操作  tip:顺序表的位序是从1开始。

int ListInsert(SeqList* L, int i, int e)   //插入操作
{
	int j;   //位置索引   1<=i<=L->length+1
	if (i<1 || i>L->length + 1) return 0;   //i值不合法
	if (L->length == L->maxsize)  return 0;   //无空间
	for (j = L->length; j >= i; j--) {
		L->data[j] = L->data[j - 1];    // L为指针变量,所以访问的时候用->x
	}
	L->data[i - 1] = e;
	L->length++;
	return 1;
}

顺序表的删除操作

int ListDelete(SeqList *L, int i, int *e)   //删除
{
	if (i<1 || i>L->length + 1) return 0;
	if (L->length == L->maxsize) return 0;
	e = L->data[i - 1];
	for (int j = i; j < L->length; j++)
	{
		L->data[j-1] = L->data[j];
	}
	L->length--;
	return 1;
}

顺序表的查找操作

int GetElem(SeqList L, int i)   // 按位查找
{
	return L.data[i - 1];
}

int LocateElem(SeqList L, int m)      // 按值查找
{
	for (int i = 0; i < L.length; i++)
	{
		if (L.data[i] == m)
			return i + 1;
	}
	return 0;
}

主函数实现

int main()
{
	SeqList L;
	InitList(&L);   //int *L=&L   表示将变量 L 的地址赋给指针 L
	ListInsert(&L, 1, 1);
	ListInsert(&L, 2, 2);
	ListInsert(&L, 3, 3);
	ListInsert(&L, 4, 4);
	ListInsert(&L, 5, 5);
	IncreaseSize(&L, 5); 
	for (int i = 0; i < L.length; i++)
	{
		printf("data[%d]=%d\n", i, L.data[i]);
	}
	int e = -2;
	if (ListDelete(&L, 1, &e))
	{
		printf("已删除第1个元素\n");
	}
	else
		printf("第i个位置不合法,删除操作失败\n");
	int i = 3;
	printf("第%d个位置的元素为%d\n", i,GetElem(L, i));
	int m = 4;
	printf("元素值为%d的元素的位置为%d\n", m, LocateElem(L, m));

	for (int i = 0; i < L.length; i++)
	{
		printf("data[%d]=%d\n", i, L.data[i]);
	}
	printf("%d\n", L.maxsize);           //  由原本的长度10增加为15
	return 0;
}

接下来实现相关算法题

1.已知一个线性表L中的数据元素按升序排列,编写一个算法,实现在线性表中插入一个数据元素item,使得线性表仍然保持升序排列。

void Insert(SeqList* L, int item)
{
	int i = 0;
    if (item >= L->data[L->length - 1])
		L->data[L->length] = item;
	else
	{
		while (item >= L->data[i])
		{
		
			i++;
		}
		ListInsert(L, i, item);  // 参数 SeqList * L 已经是一个指针类型,传递给函数时已经是地址的形式,
		//因此在函数内部直接使用 L 就可以修改传入的指针指向的内容,无需再使用取地址符号&
	}
	//L->length++;
}

因为在ListInsert函数中已经存在length++,所有不需要再使用。注意的是当调用ListInsert函数时不需要使用&符,因为此时L已经是一个地址,运行结果如下图:


2.已知一个线性表L中的数据元素按升序排列,编写一个算法,实现删除线性表中重复元素。

void Delete(SeqList* L)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < L->length; i++)
	{
		for (j = i+1; j < L->length; j++)
			if (L->data[i] == L->data[j])
			{
				printf("--%d,%d\n", i, j);
				ListDelete(L, j, L->data[j]);
			}
	}
}

上面这个算法的执行效率并不高,并且不安全,下面是参考书上的代码

void  Delete(SeqList* L)
{
	int i = 0;
	while (i < L->length - 1)
	{
		if (L->data[i] != L->data[i + 1])
			i++;
		else
			ListDelete(L, i+1,L->data[i]);
	}
}

运行结果:


3.已知两个线性表LA和LB,编写一个算法,实现将存在于线性表LB中而不存在线性表LA中的数据元素插入到LA末尾,得到新的线性表LA。

void Union(SqList& L, SqList& S)
{
	for (int i = 1; i <= S.length; i++)
	{
		
		if (!LocateElem(L, GetElem(S, i))) {
			printf("%d\n", GetElem(S, i));
			ListInsert(L, L.length + 1, GetElem(S, i));
			
			//L.length++;
		}
	}
}

两个查找方式-----按位查找和按值查找。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值