数据结构之顺序表和链表

本文详细介绍了线性表中的顺序表和链表。动态顺序表用于实际场景,初始化、销毁、增容检查、添加、删除、查找、修改和排序等功能一应俱全。顺序表的主要缺点在于插入删除效率低和增容消耗。链表概念、分类和实现被讨论,包括带头/不带头、循环/非循环的区别。链表实现关键在于头部指针,结构体指针确保链表在堆上的持久存在。
摘要由CSDN通过智能技术生成

目录

1.线性表

2.顺序表

2.1概念及结构

 2.2 接口实现

2.3 顺序表的问题及思考

3.链表

3.1 链表的概念及结构

 3.2 链表的分类

3.3 链表的实现


1.线性表

线性表 linear list n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使
用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 ...
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,
线性表在物理上存储时,通常以数组和链式结构的形式存储

2.顺序表

2.1概念及结构

顺序表是用一段 物理地址连续 的存储单元依次存储数据元素的线性结构,一般情况下采用数组存
储。在数组上完成数据的增删查改。和数组非常类似,通讯录的实现其实就是顺序表
顺序表一般可以分为:
  1. 静态顺序表:使用定长数组存储元素
  2. 动态顺序表:使用动态开辟的数组存储。

     

     2.2 接口实现

    静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致 N 定大了,空 间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间 大小,所以下面我们实现动态顺序表(通讯录)
//函数的声明
#pragma once
//放函数的声明//通讯录的声明
#include<stdio.h>
#include<string.h>
#include<assert.h>//断言防止出现空指针
#include<stdlib.h>//qsort函数头文件
//尽量少用数字,不方便修改
#define MAX 100
#define name_MAX 20
#define sex_MAX 10
#define tele_MAX 12
#define addr_MAX 20
#define all 3
#define increase 2

struct people//表示一个人的信息//存放不同类型数据用结构体
{
	int age;
	char name[name_MAX];
	char sex[sex_MAX];
	char tele[tele_MAX];
	char addr[addr_MAX];
};
//动态内存通讯录
struct contact//通讯录
{
	struct people* date;//用指针指向开辟空间的起始地址//存放数据的空间
	int sz;//已经放进去的信息
	int capcity;//容量当sz==capcity,就增容
};

2.2-1 初始化

//通讯录初始化
void init_contact(struct contact* pc)
{
	assert(pc);
	pc->sz = 0;
	pc->capcity = all;
	pc->date = (struct people*)malloc(sizeof(struct people) * all);
	if (pc->date == NULL)
	{
		perror("init_contact()");
	}

}

2.2-2 销毁

void destorycontact(struct contact* pc)
{
	free(pc->date);
	pc->date = NULL;
	pc->sz = 0;
	pc->capcity = 0;
}

2.2-3 检查是否要增容

void check(struct contact* pc)
{
	//首先要判断是否符合范围
	if (pc->sz == pc->capcity)
	{
		//增容
		struct people* ptr = (struct people*)realloc(pc->date, 
        (pc->capcity + increase) * sizeof(struct people));
		if (ptr != NULL)
		{
			pc->date = ptr;
			pc->capcity += increase;
			printf("增容成功");
		}
		else
		{
			perror("Addcontact()");
			return;
		}
	}
}

2.2-4 添加联系人的信息

void Addcontact(struct contact* pc)
{
	assert(pc);
	check(pc);
	printf("请输入名字:");
	scanf("%s", pc->date[pc->sz].name);//数组名就是首元素的地址

	printf("请输入性别:");
	scanf("%s", pc->date[pc->sz].sex);

	printf("请输入地址:");
	scanf("%s", pc->date[pc->sz].addr);
	printf("请输入电话:");
	scanf("%s", pc->date[pc->sz].tele);
	printf("请输入年龄:");
	scanf("%d", &(pc->date[pc->sz].age));//age是一个变量需要取地址
	pc->sz++;
	printf("添加联系人成功\n");
}

2.2-5 展现通讯录人所有的信息

void showcontact(struct contact* pc)
{
	//\t水平符,-代表左对齐空的用空格,后面的字符要用双引号
	printf("%-20s\t%-10s\t%-10s\t%-12s\t%-20s\n", "名字", "年龄", "性别", "地址", "电话");
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		printf("%-20s\t%-10d\t%-10s\t%-12s\t%-20s\n", pc->date[i].name, pc->date[i].age,
			pc->date[i].sex,
			pc->date[i].addr,
			pc->date[i].tele);
	}
}

2.2-6 寻找联系人(找到返回下标)

int findbyname(const struct contact* pc, char name[])//找到了ret就是下标
{
	int i = 0;
	for (i = 0; i < pc->sz; i++)
	{
		if (0 == strcmp(pc->date[i].name, name))
		{
			return i;//返回下标i
		}
	}
	return -1;
}

2.2-7 删除指定联系人

void Delcontact(struct contact* pc)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值