数据结构与算法1 简要复习

前言:此文知识点是我考前一天按照复习PPT所整理而成。而现在是2024.6.14,上午刚考完试,我还记得大概都考了什么(这个课没有真题流传)。所以如果你能看到这个博客,恭喜你挖到宝了qwq
update 2024.6.27:
本门课我总评96,是课程最高分,开心

  • 选择题:非常简单的复杂度,中序遍历,堆栈弹出,判断一个序列是大根堆小根堆还是BST。最后两道题有点不会,一个是问n个点的有向图需要几个链表存储,一个是有关后缀树(其实问的也很简单就是理解概念),但是这节课件我没太看
  • 计算题:一个线性探测的Hash很简单,一个shellsort,一个Heapify,一个2d的k-d tree,这部分都是给你一个具体的例子要你写出按照算法每一步操作过程,然后得出结果。想必这种考法相对容易。
  • 手写代码题:一个AVL的右旋和双旋函数(据说去年也考了这个),一个归并排序(去年考的快速排序)。
    至于比较担心的红黑树啊,B+树啊,Splay啊,那是只字不提,所以不用担心~

1.三种复杂度

Ο,读音:big-oh;表示上界,小于等于。

Ω,读音:big omega、欧米伽;表示下界,大于等于。

Θ,读音:theta、西塔;既是上界也是下界,称为确界,等于。

2.抽象数据类型

3.堆,栈(queue,stack)

4.哈希

  • 线性探测
  • 二次探测(重要)
  • 二次哈希

5.二叉搜索树(BST)

#include <iostream>

// 定义二叉搜索树节点
struct Node {
    int key;
    Node* left;
    Node* right;
    Node(int k) : key(k), left(NULL), right(NULL) {}
};

// 插入节点
Node* insert(Node* root, int key) {
    // 如果树为空,创建根节点
    if (root == NULL) {
        return new Node(key);
    }

    // 递归插入节点
    if (key < root->key) {
        root->left = insert(root->left, key);
    } else if (key > root->key) {
        root->right = insert(root->right, key);
    }

    // 返回根节点
    return root;
}

// 查找节点
Node* search(Node* root, int key) {
    // 如果树为空或找到目标节点,返回该节点
    if (root == NULL || root->key == key) {
        return root;
    }

    // 递归查找节点
    if (key < root->key) {
        return search(root->left, key);
    } else {
        return search(root->right, key);
    }
}

// 中序遍历
void inorderTraversal(Node* root) {
    if (root != NULL) {
        inorderTraversal(root->left);
        std::cout << root->key << " ";
        inorderTraversal(root->right);
    }
}

int main() {
    Node* root = NULL;

    // 插入节点
    root = insert(root, 50);
    root = insert(root, 30);
    root = insert(root, 20);
    root = insert(root, 40);
    root = insert(root, 70);
    root = insert(root, 60);
    root = insert(root, 80);

    // 中序遍历
    std::cout << "Inorder Traversal: ";
    inorderTraversal(root);
    std::cout << std::endl;

    // 查找节点
    Node* found = search(root, 40);
    if (found) {
        std::cout << "Found node with key: " << found->key << std::endl;
    } else {
        std::cout << "Node not found" << std::endl;
    }

    return 0;
}

6.堆

  • 二叉堆,完全二叉堆
    完全二叉堆(Complete Binary Heap)和二叉堆(Binary Heap)之间的主要区别如下:

定义:
完全二叉堆是一种特殊的二叉堆,它要求除了最底层之外,其他层的节点都是满的,且最底层的节点都集中在左侧。
二叉堆则是一种满足特定性质的二叉树,可以是完全二叉堆,也可以不是。
性质:
完全二叉堆除了最后一层外,其他层的节点都是满的。
二叉堆要求堆中任何节点的值都大于等于(小于等于)其左右子节点的值。这种性质称为堆属性。
存储:
完全二叉堆可以用数组高效地存储和表示,因为它的特殊结构。数组中的第 i 个元素的左右子节点分别是 2i+1 和 2i+2。
二叉堆也可以用数组存储,但不一定是完全二叉堆的形式。

7.AVL平衡树

LL,LR,RL,RR

#include <algorithm>
#include <iostream>

// AVL 树节点定义
struct Node {
    item data;
    int height;
    Node* lson;
    Node* rson;

    Node(item x) : data(x), height(1), lson(nullptr), rson(nullptr) {}
};

// 获取节点高度
int h(Node* t) {
    return t == nullptr ? 0 : t->height;
}

// 左旋操作
void rotateL(Node*& s) {
    Node* t = s->lson;
    s->lson = t->rson;
    t->rson = s;
    s->height = std::max(h(s->lson), h(s->rson)) + 1;
    t->height = std::max(h(t->lson), s->height) + 1;
    s = t;
}

// 右旋操作
void rotateR(Node*& s) {
    Node* t = s->rson;
    s->rson = t->lson;
    t->lson = s;
    s->height = std::max(h(s->lson), h(s->rson)) + 1;
    t->height = std::max(h(t->rson), s->height) + 1;
    s = t;
}

// 双左旋操作
void dbl_rotateL(Node*& s) {
    rotateR(s->lson);
    rotateL(s);
}

// 双右旋操作
void dbl_rotateR(Node*& s) {
    rotateL(s->rson);
    rotateR(s);
}

// 插入节点
void AVL::insert(Node*& t, item x) {
    if (t == nullptr) {
        t = new Node(x);
        return;
    }
    else if (x < t->data) {
        insert(t->lson, x);
        if (h(t->lson) == h(t->rson) + 2) {
            if (x < t->lson->data) {
                rotateL(t);
            } else {
                dbl_rotateL(t);
            }
        }
    } else if (x > t->data) {
        insert(t->rson, x);
        if (h(t->rson) == h(t->lson) + 2) {
            if (x > t->rson->data) {
                rotateR(t);
            } else {
                dbl_rotateR(t);
            }
        }
    } else {
        // 如果遇到重复值,可以选择不插入或根据需求处理
    }
    t->height = std::max(h(t->lson), h(t->rson)) + 1;
}

// 构建 AVL 树
Node* buildAVLTree(item arr[], int n) {
    Node* root = nullptr;
    for (int i = 0; i < n; i++) {
        insert(root, arr[i]);
    }
    return root;
}

int main() {
    item arr[] = {10, 20, 30, 40, 50, 25};
    int n = sizeof(arr) / sizeof(arr[0]);
    Node* root = buildAVLTree(arr, n);

    // 可以在这里添加遍历或其他操作

    return 0;
}

8.Splay平衡树

9.红黑树

https://blog.csdn.net/weixin_69519040/article/details/131396072
Red-black Tree
– Definition of null path:
• any path starting from the root where the last node is not a full node
– Properties/definitions of red/black tree
• The root must be black
• Each null path must have the same number of black nodes
• Every red node must be : a full node (with two black children), or a leaf node
• if a node P has exactly one child, it must be black and its child is red leaf node
– Be able to do two types of insertions by-hand, bottom up insertions
by-code
image

#include <iostream>
#include <cstdio>
#include <cstdlib>
using namespace std;

typedef enum { RED, BLACK } Color;

struct RBTreeNode {
    int data;
    Color color;
    struct RBTreeNode* left;
    struct RBTreeNode* right;
    struct RBTreeNode* parent;
};

RBTreeNode* createNode(int data) {
    RBTreeNode* node = (RBTreeNode*)malloc(sizeof(RBTreeNode));
    node->data = data;
    node->color = RED; 
    node->left = node->right = node->parent = NULL;
    return node;
}

// 左旋
void leftRotate(RBTreeNode** root, RBTreeNode* x){
    RBTreeNode* y = x->right;
    x->right = y->left;
    if (y->left != NULL) {
        y->left->parent = x;
    }
    y->parent = x->parent;
    if (x->parent == NULL) {
        *root = y;
    }
    else if (x == x->parent->left) {
        x->parent->left = y;
    }
    else {
        x->parent->right = y;
    }
    y->left = x;
    x->parent = y;
}

// 右旋
void rightRotate(RBTreeNode** root, RBTreeNode* y) {
    RBTreeNode* x = y->left;
    y->left = x->right;
    if (x->right != NULL) {
        x->right->parent = y;
    }
    x->parent = y->parent;
    if (y->parent == NULL) {
        *root = x;
    }
    else if (y == y->parent->right) {
        y->parent->right = x;
    }
    else {
        y->parent->left = x;
    }
    x->right = y;
    y->parent = x;
}

// 调整红黑树以维持其性质
void fixViolation(RBTreeNode** root, RBTreeNode* z) {
    while (z != *root && z->parent->color == RED) 
	{
        if (z->parent == z->parent->parent->left) {
            RBTreeNode* y = z->parent->parent->right;
            if (y != NULL && y->color == RED) {
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                z = z->parent->parent;
            }
            else {
                if (z == z->parent->right) {
                    z = z->parent;
                    leftRotate(root, z);
                }
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                rightRotate(root, z->parent->parent);
            }
        }
        else {
            RBTreeNode* y = z->parent->parent->left;
            if (y != NULL && y->color == RED) {
                z->parent->color = BLACK;
                y->color = BLACK;
                z->parent->parent->color = RED;
                z = z->parent->parent;
            }
            else {
                if (z == z->parent->left) {
                    z = z->parent;
                    rightRotate(root, z);
                }
                z->parent->color = BLACK;
                z->parent->parent->color = RED;
                leftRotate(root, z->parent->parent);
            }
        }
    }
    (*root)->color = BLACK;
}

// 插入新节点
void insert(RBTreeNode** root, int data) {
    RBTreeNode* z = createNode(data);
    RBTreeNode* y = NULL;
    RBTreeNode* x = *root;

    while (x != NULL) {
        y = x;
        if (z->data < x->data) {
            x = x->left;
        }
        else {
            x = x->right;
        }
    }
    z->parent = y;
    if (y == NULL) {
        *root = z;
    }
    else if (z->data < y->data) {
        y->left = z;
    }
    else {
        y->right = z;
    }
    fixViolation(root, z);
}

// 打印红黑树
void printTreeHelper(RBTreeNode* root, int space) {
    int COUNT = 10; // 调整这个值来控制缩进的宽度
    if (root == NULL)
        return;
    space += COUNT;
    printTreeHelper(root->right, space);
    // 打印当前节点
    printf("\n");
    for (int i = COUNT; i < space; i++)
        printf(" ");
    printf("%d(%s)\n", root->data, root->color == RED ? "R" : "B");
    printTreeHelper(root->left, space);
}

void printTree(RBTreeNode* root) {
    printTreeHelper(root, 0);
}

int main() {
    RBTreeNode* root = NULL;
    int newElement;
    /* 	
    insert(&root,22);
    insert(&root,18);
	insert(&root,36);
    insert(&root,19);
    insert(&root,30);
    printTree(root);
    */
    while (1) 
	{
        cout<<"请输入要插入的新元素(输入-1结束): ";
        cin >> newElement;
        if (newElement == -1) {
            break;
        }
        insert(&root, newElement);
        cout<<"插入 "<<newElement<<" 后的红黑树结构:\n";
        printTree(root);
        printf("\n");
    }
    return 0;
}

10.插入排序

template <typename Type>
void insertion_sort(Type *const array, int const n) {
    for (int k = 1; k < n; ++k) {
        Type value = array[k]; // Element to be inserted
        int j;
        // Shift elements of array[0..k-1], that are greater than value,
        // to one position ahead of their current position
        for (j = k; j > 0 && array[j - 1] > value; --j) {
            array[j] = array[j - 1]; // Move greater elements one position ahead
        }
        // Insert the value at its correct position
        array[j] = value;
    }
}

11.冒泡排序

(1)初始版本

template <typename Type>
void bubble(Type *const array, int const n) {
    // The outer loop controls the number of passes, with the largest element
    // "bubbling up" to its correct position at the end of each pass
    for (int i = n - 1; i > 0; --i) {
        // The inner loop is responsible for comparing and swapping adjacent elements
        // during each pass
        for (int j = 0; j < i; ++j) {
            // If the current element is greater than the next element, swap them
            if (array[j] > array[j + 1]) {
                std::swap(array[j], array[j + 1]);
            }
        }
    }
}

(2)优化一

template <typename Type>
		void bubble( Type *const array, int const n ) {
		           for ( int i = n - 1; i > 0; --i ) {
		                Type max = array[0];                     // assume array[0] is the max

		                      for ( int j = 1; j <= i; ++j ) {
		                        if ( array[j] < max ) {
		                                array[j - 1] = array[j];   // move
		                        } else {
		                                array[j – 1] = max;        // store the old max
		                                max = array[j];            // get the new max
		                        }
		                      }

		                array[i] = max;                            // store the max
		           }

(3)优化三

		template <typename Type>
		void bubble( Type *const array, int const n ) {
		           int pos;
		           for ( int i = n - 1; i > 0;) {
		                      Type max = array[0];
		               pos = 0;
		                      for ( int j = 1; j <= i; ++j ) {
		                                 if ( array[j] < max ) {
		                                           array[j - 1] = array[j];
		                                pos = j - 1;
		                                 } else {
		                                            array[j – 1] = max;
		                                            max = array[j];
		                                 }
		                      }
		                      array[i] = max;
                                   i = pos
		           }
		}

(4)优化四

#include<iostream>
using namespace std;

int a[10] = { 3,5,1,2,4,7,9,8,6,0 };
//运用四种优化方法 
void Improved4_BubbleSort(int *array, int n) {
	int lower = 0;
	int upper = n - 1;
	while (true) 
	{
		bool sorted=1; //优化2 
		int max = array[lower]; //优化1 
		int new_upper = lower;
		for (int i = lower; i < upper; ++i) 
		{
			if (array[i+1] < max) {
				array[i] = array[i + 1];
				new_upper = i;
				sorted=0;
			}
			else {
				array[i] = max;
				max = array[i + 1];
			}
		}
		if(sorted) break;
		
		array[upper] = max;
		upper = new_upper;
		if (lower == upper) {
			break;
		}
		int min = array[upper];
		int new_lower = upper;
		for (int i = upper; i > lower; --i) 
		{
			if (array[i-1] > min) {
				array[i] = array[i-1];
				new_lower = i;
				sorted=0;
			}
			else {
				array[i] = min;
				min = array[i-1];
			}
		}
		if(sorted) break;
		array[lower] = min;
		lower = new_lower;
		if (lower == upper) {
			break;
		}
	}
}


int main() 
{
	cout<<"origin: ";
	for(int i=0;i<10;i++) cout<<a[i]<<' ';
	puts("");
	Improved4_BubbleSort(a, 10);
	for(int i=0;i<10;i++) cout<<a[i]<<' ';
	return 0;
}

12.堆排序

in-place

#include<bits/stdc++.h>
using namespace std;

void Heapify(int a[], int n, int i) {
    int largest = i;
    int left = 2 * i + 1;
    int right = 2 * i + 2;

    if (left < n && a[left] > a[largest])
        largest = left;

    if (right < n && a[right] > a[largest])
        largest = right;

    if (largest != i) {
        swap(a[i], a[largest]);
        Heapify(a, n, largest);
    }
}

void BuildMaxHeap(int a[], int n) {
    for (int i = n / 2 - 1; i >= 0; i--)
        Heapify(a, n, i);
}

void HeapSort(int a[], int n) {
    BuildMaxHeap(a, n);
	int cnt=0;
    for (int i = n - 1; i > 0; i--) {
        swap(a[0], a[i]);
        Heapify(a, i, 0);
    }
}

int main() {
    int a[] = {34, 15, 65, 59, 79, 42, 40, 80, 50, 61, 23, 46};
    int n = 12;

    cout << "Original array: ";
    for (int i = 0; i < n; i++)
        cout << a[i] << " ";
    cout << endl;

    HeapSort(a, n);

    cout << "Sorted array: ";
    for (int i = 0; i < n; i++)
        cout << a[i] << " ";
    cout << endl;

    return 0;
}

13.归并排序+求逆序对

#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;

int n, a[12000], b[12000];
long long int inversions = 0;  // 用于记录逆序对的数量

void merge(int low, int mid, int high) {
    int i = low, j = mid + 1, k = low;
    while (i <= mid && j <= high) {
        if (a[i] <= a[j]) {
            b[k++] = a[i++];
        } else {
            b[k++] = a[j++];
            inversions += (mid - i + 1);  // 更新逆序对数量
        }
    }
    while (i <= mid)
        b[k++] = a[i++];
    while (j <= high)
        b[k++] = a[j++];
    for (int i = low; i <= high; i++)
        a[i] = b[i];
}

void mergesort(int x, int y) {
    if (x >= y) return;
    int mid = (x + y) / 2;
    mergesort(x, mid);
    mergesort(mid + 1, y);
    merge(x, mid, y);
}

int main() {
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> a[i];
    mergesort(1, n);  // 调用函数
    for (int i = 1; i <= n; i++)
        cout << a[i] << " ";
    cout << endl;
    cout << "逆序对数量: " << inversions << endl;
    return 0;
}

14.快速排序

Median-of-three, in-place sorting, use insertion sort when size is small

#include<iostream>
using namespace std;
void insertionsort(int array[],int low, int high) {
	for (int i = low + 1;i <= high;i++) {
		int key = array[i];
		int j = i - 1;
		while (j >= low && array[j] > key) {
			array[j + 1] = array[j];
			--j;
		}
		array[j + 1] = key;
	}
}
int middle(int array[], int low, int high) {
    int mid = low + (high - low) / 2;
    if (array[low] > array[mid]) {
        swap(array[low], array[mid]);
    }
    if (array[low] > array[high]) {
        swap(array[low], array[high]);
    }
    if (array[mid] > array[high]) {
        swap(array[mid], array[high]);
    }
    return mid;
}
int partition(int array[], int low, int high) {
    int pivotIndex = middle(array, low, high);
    int pivot = array[pivotIndex];
    swap(array[pivotIndex], array[high]);
    int i = low - 1;
    for (int j = low; j < high; ++j) {
        if (array[j] < pivot) {
            ++i;
            swap(array[i], array[j]);
        }
    }
    swap(array[i + 1], array[high]);
    return i + 1;
}
void quicksort(int array[],int low,int high) {

    if ((high - low + 1) <= 6) {
        insertionsort(array, low, high);
        return;
    }
    int pivotIndex = partition(array, low, high);
    quicksort(array, low, pivotIndex - 1);
    quicksort(array, pivotIndex + 1, high);
}
int main() {
    int n;
    cin >> n;
    int* array = new int[n];
    for (int i = 0;i < n;i++) {
        cin >> array[i];
    }
    quicksort(array, 0, n - 1);
    for (int i = 0;i < n;i++) {
        cout << array[i] << " ";
    }
	return 0;
}

15.基数排序

16.希尔排序

17.Multiway Search Tree(3-way trees)

template <typename Type>
Three_way_node *Three_way_node<Type>::find( Type const &obj ) const {
    if ( !full() ) {
        return ( first() == obj );
    }

    if ( (obj == first()) || (obj == second()) ) {
        return this;
    } else if ( obj < first() ) {
        return (  left() == nullptr) ? nulltpr :   left()->find( obj );
    } else if ( obj > second()) ) {
        return ( right() == nullptr) ? nullptr :  right()->find( obj );
    } else {
        return (middle() == nulltpr) ? nullptr : middle()->find( obj );
    }
}

template <typename Type>
bool Three_way_node<Type>::insert( Type const &obj ) {
    if ( !full() ) {
        if ( obj == first() ) {
             return false;
        } else if ( obj < first() ) {
             second_value = first();
             first_value = obj;
        } else {
             second_value = obj;
        }

        num_values = 2;
        return true;
    }

	if ( obj == first() || obj == second() ) {
        return false;
    }
    if ( obj < first() ) {
        if ( left() == nullptr ) {
            p_left_tree = new Three_way_node( obj );
            return true;
        } else {
            return left()->insert( obj );
        }
    } else if ( obj > second() ) {
        // create or insert a new node at the right sub-tree
    } else {
        // create or insert a new node at the middle sub-tree
    }
}
template <typename Type, int N>
class Multiway_node {
	private:
	    int num_values;
	    Type elements[N – 1];
	    Multiway_node *[N];  // an array of pointers to multiway nodes
	public:
	    Multiway_node( Type const & );
	    // ...
};

template<typename Type, int M>
bool M_ way_node<Type, M>::full() const {
	return ( num_values == M - 1 );
}
template <typename Type, int N>
void Multiway_node<Type, N>::in_order_traversal() const {
    if ( empty() ) {
        return;
    } else if ( !full() ) {
        for ( int i = 0; i < num_values; ++i ) {
            cout << elements[i];
        }
    } else {
        for ( int i = 0; i < N - 1; ++i ) {
            if ( subtrees[i] != nullptr ) {
                subtrees[i]->in_order_traversal();
            }
            cout << elements[i];
        }

        subtrees[N - 1]->in_order_traversal();
    }
}

18.B+树 ?

19.后缀数组,后缀树?

20.k-d tree,Quadtree,Interval tree

posted @ 2024-06-13 19:25  conprour  阅读(11)  评论(1编辑  收藏  举报