0
点赞
收藏
分享

微信扫一扫

数据结构个人笔记

天悦哥 2022-03-27 阅读 90
数据结构

数据结构

个人笔记,图片存于gitte,代码相对较多
笔记软件: typora

上传平台:https://gitee.com/Allorry/cloud-notes

文章目录

1. 时间复杂度

  1. log2 N 一般简写为 logN, 而快速排序的复杂度为 N * logN

  2. 如果要查找14亿人,而且在已经排好序的前提下,二分法: 设最多查了x次, 2^x=14亿,

  3. 所以 二分法时间复杂度:logN

  4. 递归函数的时间复杂度:递归次数 x 每次的复杂度

    ![image-20220314194601423](https://gitee.com/Allorry/cloud-notes/raw/master/img/image-20220314194601423.png

2. 线性表

typedef int type; //可以随手更改type的类型
typedef struct SqList {
	type* a;    //动态内存开辟的首地址
	type length;   //线性表当前长度
	type capacity; //线性表容量
}SqList;

void ListInit(SqList* L) {   //初始化
	//确保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. 树(堆)

概念

image-20220314195041068

image-20220314195120638

image-20220314195154611

大根堆: 父亲大于自己的孩子 小根堆: 父亲小于自己的孩子

算数

  • 规律 : 若规定根节点的层数为1,则

    1. 非空二叉树的第i层最多有2^(i-1) 个结点。
    2. 深度为h的二叉树最多有2^h-1个结点。
    3. 如果度为0的结点N0个,度为2的N2个,则N0=N2+1
  • 例题 : 如果某二叉树有399个结点,有199度为2的结点,求叶子结点数。

    ​ 199+1=200

  • 例题 : 如果一个树的结点数531 ,求树的高度

    ​ 531>512=2^9 所以10层

  • 例题image-20220314195259299

​ 如图,先把数组展开,一看B就不对

建堆

建堆: 一个随机的数组,把他改成大堆或小堆的形式。

image-20220314195314768

如图,堆 用数组进行表示,按照序号排列,初始结点为0,并且满足以上关系式。

小根堆调节算法image-20220314195327311

#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] << ' ';
}

image-20220314195347293 乱起来了,很多东西不一样

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);
}


举报

相关推荐

0 条评论