数据结构
个人笔记,图片存于gitte,代码相对较多
笔记软件: typora
上传平台:https://gitee.com/Allorry/cloud-notes
文章目录
1. 时间复杂度
-
log2 N 一般简写为 logN, 而快速排序的复杂度为 N * logN
-
如果要查找14亿人,而且在已经排好序的前提下,二分法: 设最多查了x次, 2^x=14亿,
-
所以 二分法时间复杂度:logN
-
递归函数的时间复杂度:递归次数 x 每次的复杂度
 { //初始化
//确保L不是空指针,用assert
assert(L);
L->a = NULL;
L->length = 0;
L->capacity = 0;
}
void ListDestory(SqList* L) { //销毁
assert(L);
free(L->a);
L->a = NULL;
L->length = 0;
L->capacity = 0;
}
void capacityCheck(SqList* L) { //检查是否需要增容
assert(L);
if (L->length == L->capacity) {
type* p = realloc(L->a, (L->capacity + ADD) * sizeof(type));
if (p != NULL) {
L->a = p;
L->capacity += ADD;
}
else {
perror(capacityCheck);
return;
}
}
}
void ListPushBack(SqList* L, type x) { //插入后方,以及要插入的数据x
assert(L);
capacityCheck(L);
L->a[L->length] = x;
L->length++;
}
void ListPushFront(SqList*L, type x) { //插入前方,数据x
assert(L>=1);
capacityCheck(L);
int end = L->length - 1;
while (end) {
L->a[end + 1] = L->a[end];
end--;
}
L->a[0] = x;
L->length++;
}
void ListPopBack(SqList*L) { //尾删
assert(L);
L->a[L->length - 1] = 0;
L->length--;
}
void ListPopFount(SqList* L) { //头删
assert(L);
int t = 0;
while (t < L->length-1) {
L->a[t] = L->a[t + 1];
}
L->length--;
}
int ListFind(SqList*L, type x) { //查找
assert(L);
for (int i = 0; i < L->length - 1; i++) {
if (L->a[i] == x) return i;
}
return -1;
}
int main()
{
SqList L;
ListInit(&L);
}
3. 单链表
复杂版
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int type;
typedef struct SListNode {
int data;
struct SListNode* next;
}SListNode;
void SListPrint(SListNode* plist) { //打印
SListNode* cur = plist;
while (cur != NULL) {
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
SListNode* BuyNode(type x) { //输入,构造新节点,x为值
SListNode* node = (SListNode*)malloc(sizeof(SListNode));
node->data = x;
node->next = NULL;
return node;
}
//注:为了避免首元素本身就是个NULL,以下操作将涉及对首元素的修改,
// 因此舍弃一级指针的想法,采取二级指针
void SListPushBack(SListNode** pplist, type x) { //尾插,增添元素
SListNode* cur = BuyNode(x);
// 1.NULL 2. !NULL
if (*pplist == NULL) {
*pplist = cur; //相当于cur取代NULL
return;
}
//找尾
SListNode* tail = *pplist;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = cur; //指向新的节点
}
void SListPushFront(SListNode** pplist, type x) { //首插
SListNode* cur = BuyNode(x);
cur->next = *pplist;
*pplist = cur; //调整初始位置
}
void SListPopBack(SListNode** pplist) { //尾删
// 1.NULL 2.一个节点 3.多个节点
if (*pplist == NULL) return;
if ((*pplist)->next == NULL) {
free(*pplist);
*pplist = NULL;
return;
}
SListNode* prev = NULL;
SListNode* tail = *pplist;
while (tail->next != NULL) {
prev = tail;
tail = tail->next;
}
free(tail);
tail = NULL;
prev->next = NULL;
}
void SListPopFront(SListNode** pplist) { //头删
if (*pplist == NULL) {
return;
}
SListNode* next = (*pplist)->next;
free(*pplist);
*pplist = next;
}
SListNode* SListSearch(SListNode* plist, type x) { //查找
SListNode* cur = plist;
while (cur) {
if (cur->data == x)
return cur;
cur = cur->next;
}
return NULL; //没找到
}
void SListInsertAfter(SListNode* pos, type x) { //在pos之后插入x
assert(pos);
SListNode* cur = BuyNode(x);
cur->next = pos->next; //注意顺序,不要颠倒
pos->next = cur;
}
void SListInsert(SListNode* plist, SListNode* pos, type x) { //在pos之前插入x
assert(pos);
SListNode* new = BuyNode(x);
SListNode* cur = plist;
while (cur->next != pos) {
cur = cur->next;
}
new->next = pos;
cur->next = new;
}
//投机取巧的特殊插入方式,现要求在不知道头指针的情况下,在已知pos的钱包插入x
void Insert(SListNode*pos, type x) {
//在pos后边开设一个新空间装x,然后把这俩空间的值交换一下
SListNode* cur = BuyNode(x);
cur->next = pos->next;
pos->next = cur;
type temp = cur->data; cur->data = pos->data; pos->data = temp;
}
void SListEraseAfter(SListNode*pos) {
assert(pos);
if (pos->next == NULL) return;
SListNode* next = pos->next;
pos->next = next->next;
free(next);
}
void SListEraseItself(SListNode** pplist, SListNode* pos) {
assert(pos);
if (*pplist == NULL) return;
if (*pplist == pos) { //只有一个元素
free(*pplist);
*pplist = NULL;
return;
}
SListNode* cur = *pplist;
while ((cur)->next != pos) {
cur = cur->next;
}
cur->next = pos->next;
free(pos);
pos = NULL;
}
int main() {
type x=5;
//SListNode* plist = NULL;
SListNode* plist = (SListNode*)malloc(sizeof(SListNode));
plist->data = 7;
plist->next = NULL;
SListPushBack(&plist, x); //二级指针pplist指向plist
SListPushFront(&plist, x);
SListPrint(plist);
SListPopFront(&plist);
SListPopBack(&plist);
if (SListSearch(plist, 7) != NULL) printf("yes\n");
SListPushBack(&plist, x);
SListPushBack(&plist, x);
SListNode* pos = SListSearch(plist, 5);
SListInsert(plist, pos, 3);
SListPrint(plist);
}
简易版
#include<iostream>
#include<assert.h>
#include<algorithm>
#define ADD 5
using namespace std;
typedef int type;
typedef struct ListNode{
type data;
ListNode* next;
}ListNode;
void ListInit(ListNode* l) { // 初始化头结点,不嫌麻烦,单独成函数
assert(l);
l->data = 0;
l->next = NULL;
}
ListNode* BuyNode(type x) { // 创建新节点并返回
ListNode* t = (ListNode*)malloc(sizeof(ListNode));
t->data = x;
t->next = NULL;
return t;
}
void ListPushBack(ListNode* l, type x) { //尾插
assert(l);
ListNode* cur = BuyNode(x);
ListNode* tail = l;
while (tail->next != NULL) {
tail = tail->next;
}
tail->next = cur;
}
void ListPushFront(ListNode* l, type x) { //头插,但是插入头结点后边
assert(l);
ListNode* cur = BuyNode(x);
cur->next = l->next;
l->next = cur;
}
void ListPopBack(ListNode* l) { //尾删
assert(l);
if (l->next == NULL) return; //无元素
ListNode* pre = NULL;
ListNode* tail = l;
while (tail->next != NULL) {
pre = tail;
tail=tail->next;
}
free(tail);
tail = NULL;
pre->next = NULL;
}
void ListPopFront(ListNode* l) { // 头删
assert(l);
if (l->next == NULL) return; //无元素
ListNode* t1 = l->next;
ListNode* t2 = t1->next;
free(t1);
t1 = NULL;
l->next=t2;
}
ListNode* ListSearch(ListNode* l, type x) { //查找
ListNode* cur = l->next;
while (cur) {
if (cur->data == x) return cur;
cur = cur->next;
}
return NULL;
}
void InsertAfter(ListNode* pos, type x) { //插入目标后方
assert(pos);
ListNode* cur = BuyNode(x);
cur->next = pos->next;
pos->next = cur;
}
void InsertBefore(ListNode* l, ListNode* pos, type x) { //插入目标前方
assert(pos);
ListNode* cur = BuyNode(x);
ListNode* head = l;
while (head->next != pos) {
head = head->next;
}
cur->next = pos;
head->next = cur;
}
void Insert(ListNode* pos, type x) { //不知道头结点时,投机取巧的前插方式
ListNode* cur = BuyNode(x);
swap(cur->data, pos->data);
cur->next = pos->next;
pos->next = cur;
}
void EraseAfter(ListNode* pos) { //消除后方元素
assert(pos);
if (pos->next == NULL) return;
ListNode* next = pos->next;
pos->next = next->next;
free(next);
}
void EraseItself(ListNode* l, ListNode* pos) { //我杀我自己
assert(pos);
ListNode* cur = l;
while (cur->next != pos) {
cur = cur->next;
}
cur->next = pos->next;
free(pos);
pos = NULL;
}
void ListPrint(ListNode* l) { //打印,但别打印头结点
ListNode* cur = l->next;
while (cur) {
printf("%d ", cur->data);
cur = cur->next;
}
puts("");
}
int main()
{
//ListNode* l =nullptr 别赋空指针
ListNode* l = (ListNode*)malloc(sizeof(ListNode)); //作为头结点,别妄图大幅修改
ListInit(l);
ListPushBack(l, 1);
ListPushBack(l, 2);
ListPushBack(l, 3);
ListPushBack(l, 4);
ListPushBack(l, 5);
ListPushFront(l, 8);
ListPushFront(l, 9);
ListPrint(l);
ListPopFront(l);
ListPopBack(l);
ListPrint(l);
ListNode* t = ListSearch(l, 3);
InsertAfter(t, 11);
InsertBefore(l, t, 12);
Insert(t, 99);
ListPrint(l);
EraseAfter(t);
EraseItself(l, t);
ListPrint(l);
}
4. 带头双向链表
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int type;
typedef struct ListNode {
type data;
struct ListNode* next;
struct ListNode* prev;
}ListNode;
ListNode* BuyNode(type x) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->next = NULL;
node->prev = NULL;
return node;
}
ListNode* ListInit() {
ListNode* phead = BuyNode(0);
phead->next = phead;
phead->prev = phead;
return phead;
}
void ListPrint(ListNode* phead) {
ListNode* cur = phead->next;
while (cur != phead) {
printf("%d ", phead->data);
cur = cur->next;
}
printf("\n");
}
void ListPushBack(ListNode* phead, type x) {
assert(phead);
ListNode* tail = phead->prev;
ListNode* newnode = BuyNode(x);
tail->next = newnode;
newnode->prev = tail;
newnode->next = phead;
phead->prev = newnode;
}
void ListPushFront(ListNode* phead, type x) {
asset(phead);
ListNode* first = phead->next;
ListNode* newnode = BuyNode(x);
phead->next = newnode;
newnode->next = first;
newnode->prev = phead;
first->prev = newnode;
}
void ListPopBack(ListNode* phead) {
assert(phead);
if(phead->p==phead) return;
ListNode* tail = phead->prev;
ListNode* tailPrev = tail->prev;
free(tail);
tailPrev->next = phead;
phead->prev = tailPrev;
}
void ListPopFront(ListNode* phead) {
assert(phead);
if(phead->next==phead) return;
ListNode* first = phead->next;
ListNode* second = first->next;
free(first);
phead->next = second;
second->prev = phead;
}
void ListInsert(ListNode* pos, type x) {
assert(pos);
ListNode* prev = pos->prev;
ListNode* newnode = BuyNode(x);
prev->next = newnode;
newnode->prev = prev;
newnode->next = pos;
pos->prev = newnode;
}
void ListErase(ListNode* pos) {
assert(pos);
ListNode* prev = pos->prev;
ListNode* next = pos->next;
prev->next = next;
next->prev = prev;
free(pos);
}
void ListNodeDestory(ListNode* phead) {
assert(phead);
ListNode* cur = phead->next;
while (cur != phead) {
ListNode* next = cur->next;
free(cur);
cur = next;
}
free(phead);
phead = NULL;
}
5. 栈
#define ADD 4
#include<stdbool.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int type;
typedef struct Stack {
type* a;
type top; //top可以表示栈中元素数目,引用最上层时用top-1
type capacity;
}Stack;
void StackInit(Stack* pst) {
assert(pst);
pst->a = (type*)malloc(sizeof(Stack) * ADD);
pst->top = 0;
pst->capacity = ADD;
}
void StackPush(Stack* pst, type x) {
assert(pst);
if (pst->top == pst->capacity) {
type* temp = (type*)realloc(pst->a, sizeof(Stack) * (pst->capacity + ADD));
if (temp == NULL) {
printf("扩容失败");
exit(-1);
}
pst->a = temp;
pst->capacity += ADD;
}
pst->a[pst->top] = x;
pst->top++;
}
bool StackEmpty(Stack* pst) {
assert(pst);
return pst->top == 0;
}
int StackSize(Stack* pst) {
assert(pst);
return pst->top;
}
void StackPop(Stack* pst) {
assert(pst);
assert(StackEmpty(pst));
pst->top--;
}
int main(){
Stack s;
StackInit(&s);
}
6. 队列
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int type;
typedef struct QueueNode {
struct QueueNode* next;
type data;
}QueueNode;
typedef struct Queue {
QueueNode* head;
QueueNode* tail;
}Queue;
void QueueInit(Queue* pq) {
pq->head = pq->tail = NULL;
}
void QueueDestory(Queue* pq) {
QueueNode* cur = pq->head;
while (cur) {
QueueNode* next = cur->next;
free(cur);
cur = next;
}
pq->head = pq->tail = NULL;
}
void QueuePush(Queue* pq, type x) { //带
assert(pq);
QueueNode* newnode = (QueueNode*)malloc(sizeof(QueueNode));
if (newnode == NULL) {
printf("malloc fail\n");
exit(-1);
}
newnode->data = x;
newnode->next = NULL;
if (pq->tail == NULL) {
pq->head = pq->tail = newnode;
}
else {
pq->tail->next = newnode;
pq->tail = newnode;
}
}
void QueuePop(Queue* pq) {
assert(pq);
assert(pq->head);
if (pq->head->next==NULL) {
free(pq->head);
pq->head = pq->tail = NULL;
}
else {
QueueNode* next = pq->head->next;
free(pq->head);
pq->head = next;
}
}
void QueuePrint(Queue* pq) {
assert(pq);
QueueNode* cur = pq->head;
while (cur) {
printf("%d ", cur->data);
cur = cur->next;
}
printf("\n");
}
int main()
{
Queue pq;
QueueInit(&pq);
QueuePush(&pq, 1);
QueuePush(&pq, 2);
QueuePush(&pq, 3);
QueuePush(&pq, 4);
QueuePrint(&pq);
system("pause");
QueuePop(&pq);
QueuePrint(&pq);
}
7. 树(堆)
概念
大根堆: 父亲大于自己的孩子 小根堆: 父亲小于自己的孩子
算数
-
规律 : 若规定根节点的层数为1,则
- 非空二叉树的第i层最多有2^(i-1) 个结点。
- 深度为h的二叉树最多有2^h-1个结点。
- 如果度为0的结点N0个,度为2的N2个,则N0=N2+1
-
例题 : 如果某二叉树有399个结点,有199度为2的结点,求叶子结点数。
199+1=200
-
例题 : 如果一个树的结点数531 ,求树的高度
531>512=2^9 所以10层
-
例题 :
如图,先把数组展开,一看B就不对
建堆
建堆: 一个随机的数组,把他改成大堆或小堆的形式。
如图,堆 用数组进行表示,按照序号排列,初始结点为0,并且满足以上关系式。
小根堆调节算法 :
#include<iostream>
using namespace std;
inline void swap(int& a, int& b) {
int t = a;
a = b;
b = t;
}
inline void AdjustDown(int* a, int n, int parent) { //核心
int child = parent * 2 + 1; //左孩子
while (child < n) {
if (child + 1 < n && a[child] > a[child + 1]) { //选出左右中小的那个
child++; //若改为大根堆,a[child]<a[child+1] 选出大的
}
if (a[child] < a[parent]) { //若改为大根堆,a[child]>a[parent]
swap(a[child], a[parent]);
parent = child;
child = parent * 2 + 1;
}
else break;
}
}
int main()
{
int a[] = { 23,15,19,18,28,34,65,49,25,37 };
int n = sizeof(a) / sizeof(int);
AdjustDown(a, n, 0);
for (int i = 0; i < n; i++) cout << a[i] << ' ';
}
乱起来了,很多东西不一样
int a[]={15,18,28,64,65,19,49,25,37,27};
for(i=(n-1 -1)/2;i>=0;i--) AdjustDown(a,n,i);
全操作
#include<iostream>
#include<assert.h>
#include<cmath>
#include<iomanip>
#define ADD 5
using namespace std;
typedef int type;
typedef struct {
type* a;
int size;
int capacity;
}heap;
void AdjustDown(type* a, int n, type parent) {
int child = parent * 2 + 1;
while (child < n) {
if (child + 1 < n && a[child] < a[child + 1]) child++;
if (a[parent] < a[child]) {
swap(a[child], a[parent]);
parent = child;
child = parent * 2 + 1;
}
else {
break;
}
}
}
void AdjustUp(type* a, type child) {
int parent = (child - 1) / 2;
while (child > 0) {
if (a[child] > a[parent]) {
swap(a[child], a[parent]);
child = parent;
parent = (child - 1) / 2;
}
else {
break;
}
}
}
void HeapInit(heap* php, type* a, int n) { //初始化,建大堆
assert(php);
//php->a = (type*)malloc(sizeof(type) * n);
php->a = new type[n];
if (php->a == NULL) {
printf("malloc fail\n");
exit(-1);
}
memcpy(php->a, a, sizeof(type) * n);
php->size = php->capacity = n;
//建堆
for (int i = (n - 1 - 1) / 2; i >= 0; i--) {
AdjustDown(php->a, php->size, i);
}
}
void HeapDestory(heap* php) {
assert(php);
delete []php->a;
php->a = nullptr;
php->size = php->capacity = 0;
}
void HeapPrint(heap* php) {
int n = 1, k = 0,i=0;
while(k<php->size) {
printf("%-3d", php->a[k++]);
i++;
if (i % n == 0) {
puts("");
n *= 2;
i = 0;
}
}
puts("");
}
void HeapPush(heap* php, type x) {
assert(php);
if (php->size == php->capacity) {
type* t = (type*)realloc(php->a, (php->capacity + ADD) * sizeof(type));
if (t == nullptr) {
printf("realloc fail\n");
exit(-1);
}
else {
php->a = t;
php->capacity += ADD;
}
}
php->a[php->size] = x;
AdjustUp(php->a, php->size);
php->size++;
}
void HeapPop(heap* php) {
assert(php);
assert(php->size > 0);
swap(php->a[php->size - 1], php->a[0]);
php->size--;
AdjustDown(php->a, php->size, 0);
}
int main()
{
int a[] = { 15,18,28,34,65,19,49,25,37,7 };
int n = sizeof(a) / sizeof(int);
heap php;
HeapInit(&php, a, n);
HeapPrint(&php);
HeapPush(&php, 10);
HeapPush(&php, 20);
HeapPush(&php, 100);
HeapPrint(&php);
HeapPop(&php);
HeapPop(&php);
HeapPop(&php);
HeapPrint(&php);
}
puts("");
n *= 2;
i = 0;
}
}
puts("");
}
void HeapPush(heap* php, type x) {
assert(php);
if (php->size == php->capacity) {
type* t = (type*)realloc(php->a, (php->capacity + ADD) * sizeof(type));
if (t == nullptr) {
printf(“realloc fail\n”);
exit(-1);
}
else {
php->a = t;
php->capacity += ADD;
}
}
php->a[php->size] = x;
AdjustUp(php->a, php->size);
php->size++;
}
void HeapPop(heap* php) {
assert(php);
assert(php->size > 0);
swap(php->a[php->size - 1], php->a[0]);
php->size–;
AdjustDown(php->a, php->size, 0);
}
int main()
{
int a[] = { 15,18,28,34,65,19,49,25,37,7 };
int n = sizeof(a) / sizeof(int);
heap php;
HeapInit(&php, a, n);
HeapPrint(&php);
HeapPush(&php, 10);
HeapPush(&php, 20);
HeapPush(&php, 100);
HeapPrint(&php);
HeapPop(&php);
HeapPop(&php);
HeapPop(&php);
HeapPrint(&php);
}