文章目录
文章为学习笔记记录,学习内容来自b站 《数据结构与算法 已完结(CLion 2022 最新版)》
后续会学到哪里就将笔记更新到哪里
不会记录太多内容,基本的编码实现C语言掌握好了,实现较为简单,主要是理解“结构”(物理、逻辑结构)
一、线性表(Linear list)
线性表的几个特征和概念:
- 数据元素同类型
- 有序序列
- 线性结构
- 长度
- 表头
- 表尾
- 空表
1. 线性表功能
- 初始化 init
- 插入 insert
- 删除 delete
- 索引 get
- 查找 find
2. 线性表分类
- 顺序存储:顺序表
- 链式存储:单链表、双链表(双向链表)、循环链表
解释:
1.顺序表是以数组为基础实现的(采用动态申请堆内存)
2.链式表中的循环链表只是单纯的将表尾和head表头链接起来形成,可分为循环单链表、循环双链表
2.1 顺序表(Sequenatial list)
时间复杂度 思考:
- 插入 O(n)
- 删除 O(n)
- 索引 O(1)
- 查找 O(n)
注意事项:顺序表是以数组为基础实现的,采用物理上顺序存储,访问可以实现按下标的随机访问,访问效率较高,查找、插入、删除需要挪动几乎遍历整个表,所以效率较低。
#include <stdio.h>
#include <stdlib.h>
typedef int E;
struct Sequenatial_list {
E * array_list;
int size;
int capacity;
};
typedef struct Sequenatial_list * Sq_List;
_Bool init_Sq_List(Sq_List list) {
list->size = 0;
list->capacity = 10;
list->array_list = (E *)malloc(sizeof(E) * list->capacity);
if (list->array_list == NULL) return 0;
return 1;
}
void print_Sq_List(Sq_List list) {
for(int i=0; i<list->size; i++)
printf("%d ", list->array_list[i]);
printf("\n");
}
_Bool insert_Sq_List(Sq_List list, E element, int index) {
if (index < 1 || index > list->size + 1) return 0;
if (list->size == list->capacity) {
int newCapacity = list->capacity + (list->capacity >> 1);
E *newArrayList = (E *)realloc(list->array_list, sizeof(E) * newCapacity);
if (newArrayList == NULL) return 0;
list->array_list = newArrayList;
list->capacity = newCapacity;
}
for (int i=list->size; i>index-1; i--) {
list->array_list[i] = list->array_list[i-1];
}
list->array_list[index-1] = element;
list->size++;
return 1;
}
_Bool delete_Sq_List(Sq_List list, int index) {
if (index < 1 || index > list->size) return 0;
for (int i=index-1; i<list->size-1; i++)
list->array_list[i] = list->array_list[i+1];
list->size--;
return 1;
}
E *get_Sq_List(Sq_List list, int index) {
if (index < 1 || index > list->size) return NULL;
return &list->array_list[index-1];
}
int find_Sq_List(Sq_List list, E element) {
for (int i=0; i<list->size; i++) {
if (list->array_list[i] == element) return i+1;
}
return -1;
}
int size_Sq_List(Sq_List list) {
return list->size;
}
int main() {
struct Sequenatial_list sqlist;
init_Sq_List(&sqlist);
insert_Sq_List(&sqlist, 2, 1);
insert_Sq_List(&sqlist, 1, 2);
insert_Sq_List(&sqlist, 3, 2);
insert_Sq_List(&sqlist, 4, 1);
for (int i=0; i<20; i++)
insert_Sq_List(&sqlist, i*10, i);
delete_Sq_List(&sqlist, 2);
print_Sq_List(&sqlist);
printf("%d\n", size_Sq_List(&sqlist));
return 0;
}
2.2 单链表(Singly linked list)
时间复杂度 思考:
- 插入 O(n)
- 删除 O(n)
- 索引 O(n)
- 查找 O(n)
注意事项:
1、虽然要先找到前驱结点,但单链表插入和删除不需要挪动后续的所有元素,所以效率比顺序表高一些;
2、单链表不支持随机访问,所以索引效率比顺序表要慢;
3、读取效率顺序表高,插入和删除效率链表要高
#include <stdio.h>
#include <stdlib.h>
typedef int E;
struct Singly_linked_list {
E element;
struct Singly_linked_list *next;
};
typedef struct Singly_linked_list * Sl_List;
void init_Sl_list (Sl_List head) {
head->next = NULL;
}
void pirnt_Sl_list (Sl_List he