SeqList.h
#pragma once
#define _CRT_SECURE_WARNINGS
//可扩容的顺序表
typedef int ELEMTYPE;//对数据元素的类型进行重定义
//定义初始的格子数量
#define INITSIZE 10
typedef struct SeqList {
//1.一维数组用来存放一会的数据元素
//2.有效元素个数:既可以告诉我有效元素个数,也告诉我顺序表的末尾在哪
//3.总的格子数量(以格子为单位)
ELEMTYPE *arr;
int length;
int maxsize;
}SeqList,*PSeqList;
//1.初始化函数
void Init_Seqlist(SeqList* psq);
//2.购买新节点 //单链表的函数
//3.头插
bool Insert_Head(SeqList* psq, ELEMTYPE val);
//4.尾插
bool Insert_Tail(SeqList* psq, ELEMTYPE val);
//5.按位置插
bool Insert_Pos(SeqList* psq, ELEMTYPE val, int pos);
//6.头删
bool Del_Head(SeqList* psq);
//7.尾删
bool Del_Tail(SeqList* psq);
//8.按位置删
bool Del_Pos(SeqList* psq, int pos);
//9.按值删(只删除这个值出现的第一次)
bool Del_Val_First(SeqList* psq, ELEMTYPE val);
//10.按值删(删除这个值出现的所以位置)
bool Del_Val_ALL(SeqList* psq, ELEMTYPE val);
//11.查找(查找这个值出现的位置, 返回其下标即可)
int Search_Seqlist(SeqList* psq, ELEMTYPE val);
//12.判空
bool IsEmpty(SeqList* psq);
//13.判满
bool IsFull(SeqList* psq);
//14.扩容函数
void Increase(SeqList* psq);
//15.获取有效度长度
int Get_Length(SeqList* psq);
//16.清空
void Clear(SeqList* psq);
//17.销毁
void Destroy(SeqList* psq);
//18.打印
void Show(SeqList* psq);
SeqList.cpp
#include"SeqList.h"
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//3.4
/*
基础阶段:
1.基础概念
2.顺序表(定长,不定长)
3.单链表(带头节点,不带头节点)--较为重要
4.双向链表/单循环链表
5.链表相关的习题
6.栈(顺序表/链栈)
7.队列(循环队列/链式队列)
8.栈和队列的相关习题
9.哈希基础,哈希函数的构造,哈希冲突的解决方式(散列)
10.哈希技术的扩展(一致性哈希+虚拟结点,布隆过滤器)
11.字符串匹配(BF,KMP及其next数组的再次优化)
八大排序:
1.直接插入排序+希尔排序
2.选择排序+堆排序
3.基数排序+归并排序
4.冒泡排序+快速排序(递归实现+非递归实现)
5.快速排序如何优化,八大排序总结
基础阶段性考试
树图
1.树,二叉树的相关基础概念
2.二叉树构造方法,二叉树前中后序遍历(递归/非递归)
3.二叉搜索树(BST Binary Search/Sort Tree)
4.AVL树
5.红黑树
6.B-树
7.B+树
图
迪杰斯特拉 弗洛伊德算法
克鲁斯卡尔
书籍推荐:
数据结构(C语言)严蔚敏
大话数据结构
*/
/*
线性表:
1.有唯一的头
2.有唯一的尾
3.除了头之外,剩余的都有直接前驱
4.除了尾之外,剩余的都有直接后继
顺序存储->顺序表
用一块地址连续的空间,来存放线性表中的数据元素
特点:物理地址连续,逻辑上也是连续的(逻辑上指的是1后面是2)
链式存储->链表
特点:物理地址不连续,逻辑上是连续的
顺序表:
1.数组arr(存放数据元素)
2.有效长度length(即表示元素个数,也表示尾巴在哪)->右边界
3.MAXSIZE总的格子数量,总的空间大小
三者放在一个结构体里
增删查的三个功能
*/
//1.初始化函数
void Init_Seqlist(SeqList* psq) {
assert(psq != NULL);
if (psq == NULL)//realease版本会删掉断言 因此这个是必要的
return;
psq->arr = (ELEMTYPE *)malloc(INITSIZE * sizeof(int));//确保psq是可以被解引用的
if (psq->arr == NULL) {
exit(EXIT_FAILURE);
psq->length = 0;
psq->maxsize = INITSIZE;
}
}
//2.购买新节点 //单链表的函数
//3.头插
bool Insert_Head(SeqList* psq, ELEMTYPE val) {
//0.安全性判断
assert(psq != NULL);
if (psq == NULL) {
return 0;
}
//1.判满 满了就扩容,没满就正常运行
if (IsFull(psq)) {
Increase(psq);//直接使用变量即可,不必重新声明写成SeqList * psq;
}
//2.将现有的所有元素统一向后移动 尾巴先动
for (int i = psq->length - 1; i >= 0; i--) {
psq->arr[i + 1] = psq->arr[i];
}
//3.将100插入到最头部的位置(空出来的0号下标)
psq->arr[0] = val;
//4.处理一下length++
psq->length++;
//5.返回一下真
return true;
}
//4.尾插 效率比头部插入高
bool Insert_Tail(SeqList* psq, ELEMTYPE val) {
//0.安全性检查
assert(psq != NULL);
if (psq == NULL) {
return 0;
}
//1.判满
if (IsFull(psq)) {
Increase(psq);
}
//2.将200插入尾部
psq->arr[psq->length] = val;
//3.处理length
psq->length++;
//4.返回值
return true;
}
//5.按位置插
bool Insert_Pos(SeqList* psq, ELEMTYPE val, int pos) {//最开始都是判断传进去的参数合不合法
//0.安全性检查
assert(psq != NULL);
assert(pos >= 0 && pos <= psq->length);
//1.判满,满了就扩容
if (IsFull(psq)) {
Increase(psq);
}
//2.后移 ,注意先移动尾部
for (int i = psq->length - 1; i >= pos; i--) {
psq->arr[i + 1] = psq->arr[i];
}
//3.插入
psq->arr[pos] = val;
//4.有效元素
psq->length++;
//5.返回
return true;
}
//6.头删
bool Del_Head(SeqList* psq) {
//0.安全性检查
assert(psq != NULL);
if (psq == NULL) {
return false;
}
//1.判空,空了就删不了,返回假
if (IsEmpty(psq)) {
return false;
}
//2.将第二个元素及其后续所有元素整体前移一个格子(注意头先动)
for (int i = 1; i <= psq->length - 1; i++) {//或者i<=length
psq->arr[i - 1] = psq->arr[i];
}
//3.有效元素个数减一
psq->length--;
//4.返回真
return true;
}
//7.尾删
bool Del_Tail(SeqList* psq) {
//0.安全性检查
assert(psq != NULL);
if (psq == NULL) {
return false;
}
//1.判空
if (IsEmpty(psq)) {
return false;
}
//2.删除
psq->length--;//psq->arr[psq->length - 1] = 0;<-这个写法不大好
//3.返回真
return true;
}
//8.按位置删
bool Del_Pos(SeqList* psq, int pos) {
//0.安全性检查
/*assert(psq != NULL);
assert(pos >= 0 && pos < psq->length - 1);
//1.判空
if (IsEmpty(psq)) {
return false;
}
if (pos == psq->length - 1) {
Del_Tail(psq);
}
//2.删除(前移)
for (int i = pos + 1; i <= psq->length - 1; i++) {
psq->arr[i - 1] = psq->arr[i];
}
//3.修改有效元素
psq->length--;
//4.返回值
return true;
*/
//老师版本:
assert(psq != NULL);
assert(pos >= 0 && pos < psq->length - 1);
if (IsEmpty(psq)) {
return false;
}
for (int i = pos + 1; i <= psq->length - 1; i++) {
psq->arr[i - 1] = psq->arr[i];
}
psq->length--;
}
//9.按值删(只删除这个值出现的第一次)
bool Del_Val_First(SeqList* psq, ELEMTYPE val) {
//0.安全性检查
assert(psq != NULL);
//1.判空
if (IsEmpty(psq)) {
return false;
}
//2.找第一次出现的数
int k = Search_Seqlist(psq, val);
if (k == -1) {
return false;
}
//3.删除
for (int i = k + 1; i <psq->length; i++) {
psq->arr[i - 1] = psq->arr[i];
}
//4.改元素
psq->length--;
//5.返回值
return true;
}
//10.按值删(删除这个值出现的所有位置)
bool Del_Val_ALL(SeqList* psq, ELEMTYPE val) {
assert(psq != NULL);
if (IsEmpty(psq)) {
return false;
}
for (int i = 0; i < psq->length; i++) {
if (psq->arr[i] == val) {
for (int j = i + 1; j < psq->length; j++) {
psq->arr[j - 1] = psq->arr[j];
}
psq->length--;
i--;
}
}
return true;
//老师版本
//法一:重新申请一块空间
//法二:双指针法
/*int i = 0;
int j = 0;
while (j <= psq->length - 1) {
if (psq->arr[j] != val) {
psq->arr[i]=psq->arr[j];
i++;
j++;
}
else {
j++;
}
psq->length = i;
}
return true;
}*/
//11.查找(查找这个值出现的位置, 返回其下标即可,找一次)
int Search_Seqlist(SeqList * psq, ELEMTYPE val) {
for (int i = 0; i < psq->length; i++) {
if (val == psq->arr[i]) {
return i;//一旦查找立即返回
}
}
return -1;//找不到就返回错误标记 负数都是错误表记
}
//12.判空
bool IsEmpty(SeqList* psq) {
return psq->length == 0;
}
//13.判满
bool IsFull(SeqList* psq) {
return psq->length == psq->maxsize;
}
//14.扩容函数 !!!较为重要
void Increase(SeqList* psq) {
ELEMTYPE* tmp = (ELEMTYPE*)(realloc(psq->arr, psq->maxsize * sizeof(ELEMTYPE) * 2));//起始位置,总的大小
if (tmp != NULL) {
psq->arr = tmp;
}
psq->maxsize * 2;
}
//15.获取有效度长度
int Get_Length(SeqList* psq);
//16.清空
void Clear(SeqList* psq){
psq->length = 0;
}
//17.销毁(malloc申请的空间要销毁)
void Destroy(SeqList* psq) {
free(psq->arr);
psq->arr = NULL;
psq->length = 0;
psq->maxsize = 0;
}
//18.打印
void Show(SeqList* psq) {
for (int i = 0; i < psq->length; i++) {
printf("%d ", psq->arr[i]);
printf("\n");
}
}
int main() {
SeqList head;
Init_SeqList(&head);
Insert_Tail(&head, 12);
Insert_Tail(&head, 23);
Insert_Tail(&head, 34);
Insert_Tail(&head, 1);
Insert_Tail(&head, 2);
Insert_Tail(&head, 3);
}