数据结构
数据结构(Data Structures):是计算机存储和组织数据的一种方式,可以用来高效地处理数据。
什么样的程序才是好的程序?好的程序设计无外乎两点,“快"和"省”。"快"指程序执行速度快,高效,"省"指占用更小的内存空间。这两点其实就对应"时间复杂度"和"空间复杂度"的问题。
举个例子:二分查找就是一个非常经典的算法,而二分查找经常需要作用在一个有序数组上。这里二分就是一种折半的算法思想, 而数组是我们最常用的一种数据结构,支持根据下标快速访问。很多算法需要特定的数据结构来实现,所以经常把它们放到一块讲。
实际上,在真正的项目开发中,大部分时间都是 从数据库取数据 —> 数据操作和结构化 —> 返回给前端,在数据操作过程中需要合理地抽象、 组织、处理数据,如果选用了错误的数据结构,就会造成代码运行低效。这也是我们需要学习算法和数据结构的原因。
数据结构之队列
什么是队列:
队列是一种受限的线性表数据结构,只支持两个操作:入栈push()和出栈pop0,队列跟非常相似,支持的操作也 ,很有限,最基本的操作也是两个:入队enqueue(),放一个数据到队列尾部;出队dequeue0),从队列头部取一个元素。
普通队列
环形队列
数据结构之链表
#include <stdlib.h>
#include <string.h>
#include<stdio.h>
#pragma warning(disable:4996)
struct user_t {
int id;
int age;
struct user_t* next;
};
//请实现删除链表中所有age匹配的元素,并且返回链表头
struct user_t remove_user_by_age(struct user_t* head, int age) {
struct user_t* current = head;
if (head == NULL) {
return *head; //如果是空链表直接返回
}
if (head->age == age) {
struct user_t* current = head;
head=head->next;
current->next = NULL;
}
//创建2个赋值指针变量
struct user_t* pPrv = head;
struct user_t* pCurrent = head->next;
while (pCurrent!= NULL) {
if (pCurrent->age == age) {
pPrv->next = pCurrent->next;
pCurrent = pCurrent->next;
continue;
}
pPrv = pCurrent;
pCurrent = pCurrent->next;
}
return *head;
}
//遍历链表
void for_eachlist(struct user_t* head) {
if (head == NULL) {
return;
}
struct user_t* current = head;
while (current != NULL) {
printf("id:%d,age:%d\n", current->id, current->age);
current = current->next;
}
}
int main() {
//建立一个长度为3个链表
struct user_t list1 = { 1,20,NULL };
struct user_t list2 = { 2,30,NULL };
struct user_t list3 = { 3,40,NULL };
struct user_t list4 = { 4,50,NULL };
list1.next = &list2;
list2.next = &list3;
list3.next = &list4;
for_eachlist(&list1);
printf("\n");
struct user_t newhead = remove_user_by_age(&list1, 50);
for_eachlist(&newhead);
return 0;
}
算法
算法(Algorithm):是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制。也就是说,能够对一定规模的输入,在有限时间内获得所要求的输出。(任何代码片段都可视为算法)
算法本质就是高效解决问题的方法。
复杂度归类
冒泡排序、插入排序、选择排序 O(n^2)
快速排序、归并排序 O(nlogn)
冒泡排序法
冒泡排序:相邻两个元素比较,前面比后面的大,两个元素交换
template<typename T>
void bubleSort(T arr[], int n) {
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++){
if (arr[j] > arr[j+1])
swap(arr[j], arr[j+1]);
}
}
}
选择排序法 SelectSort
template<typename T>
void selectionSort(T arr[],int n){
for (int i = 0; i < n; i++) {
int minIndex = i; //这里int写成T报错
for (int j = i+1; j < n; j++) {
if (arr[j] < arr[minIndex]){
minIndex = j;
}
}
swap(arr[i], arr[minIndex]);
}
}
插入排序法
template<typename T>
void finalInsertSort(T arr[], int n) {
for (int i = 0; i < n - 1; i++) {
//寻找arr[i]最适合插入的位置
T e = arr[i];
int j=i+1;
for (j = i+1;j>0 &&arr[j-1]>e;j--) {
arr[j] = arr[j - 1];
}
arr[j] = e;
}
}
归并排序法
//将arr[left,mid]和arr[mid+1,right]两部分进行归并
template<typename T>
void __merge(T arr[], int left, int mid, int right) {
T aux[right - left + 1]; //申请同样大的空间
//T *aux=new T[right-left+1];
for (int i = left; i <= right; i++) {
aux[i-left] = arr[i];
}
int i = left, j = mid + 1;
for (int k = left; k <= right; k++) {
if (i>mid) {
arr[k] = aux[j - left];
j++;
}
else if(j>right){
arr[k] = aux[i - left];
i++;
}
else if (aux[i-left]<aux[j-left]) {
arr[k] = aux[i - left];
i++;
}
else {
arr[k] = aux[j - left];
j++;
}
}
}
//递归使用归并排序.对arr[left,right]的范围进行排序
template<typename T>
void __mergeSort(T arr[], int left, int right) {
if (left >= right)
return;
int mid = (left + right) / 2;
//int mid=left+(right-left)>>2;
__mergeSort(arr, left, mid);
__mergeSort(arr, mid + 1, right);
__merge(arr, left, mid, right);
}
template<typename T>
void mergeSort(T arr[], int n) {
__mergeSort(arr, 0, n - 1);
}
二分查找法Binary Search
#include<iostream>
using namespace std;
template<typename T>
int binarySearch(T arr[], int n, T target) {
int left = 0, right = n - 1;
while (left <= right) {
// int mid = (left + right) / 2; //with bug overflow
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid;
}
if (arr[mid] > target) {
right = mid - 1;
}
else {
left = mid + 1;
}
}
return -1;
}
int main() {
int arr[] = {1,2,3,4,5,6,7,8,9,10};
int n=binarySearch(arr,10,8);
cout << n << endl;
system("pause");
return 0;
}
二分搜索树
#include<iostream>
using namespace std;
template<typename Key,typename Value>
class BST {
private:
struct Node {
Key key;
Value value;
Node *left;
Node *right;
//节点的构造函数
Node(Key key, Value value) {
this->key = key;
this->value = value;
this->left = this->right = NULL;
}
Node* root;
int count;
public:
BST() {
root = NULL;
count = 0;
}
~BST() {
//TODO
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
//return root==NULL
}
};
};
int main() {
return 0;
}
二分搜索树的前中后序遍历
前序遍历:先访问当前节点,再依此递归访问左右子树
中序遍历:先递归访问左子树,再访问自身,再递归访问右子树
后续遍历:先递归访问左右子树,再访问自身节点
#include<iostream>
using namespace std;
template<typename Key,typename Value>
class BST {
private:
struct Node {
Key key;
Value value;
Node* left;
Node* right;
//节点的构造函数
Node(Key key, Value value) {
this->key = key;
this->value = value;
this->left = this->right = NULL;
}
};
Node* root;
int count;
public:
BST() {
root = NULL;
count = 0;
}
~BST() {
//TODO
destory(root);
}
int size() {
return count;
}
bool isEmpty() {
return count == 0;
//return root==NULL
}
void insert(Key key) {
root=insert(root, key);
}
bool contain(Key key, Value value) {
return contain(root,key,value);
}
Value* search(Key key){
return search(root, key);
}
public:
//向以node为根的二叉搜索树中,插入节点(key,value)
//返回插入新节点后的二叉搜索树的根
//------------------------------------------------------------------------插入树递归方法------------------------------------------------------
//Node* insert(Node* node, Key key, Value value) {
// if (node == NULL) {
// count++;
// return new Node(key,value);
// }
// else if (key <node->key) {
// node->left=insert(node->left, key, value);
// }
// else if (key > node->key) {
// node->right=insert(node->right, key, value);
// }
// else { //key==node->key
// node->value = value;
// }
// return node;
//
//}
//----------------------------------------------------------------插入树非递归方法-----------------------------------------------
Node* insert(Node* node, Key key, Value value) {
Node* p = node;
if (node == NULL) {
count++;
p=new Node(key, value); //记录根节点
return p;//返回根节点
}
while (1) {
if (node == NULL) {
count++;
new Node(key, value);
return p;//返回根节点
}else if(key < node->key) {
node = node ->left;
continue;
}else if (key > node->key) {
node = node->right;
continue;
}else{ //相等
node->value = value;
return p;
}
}
}
//---------------------------------------------------------递归查找树-----------------------------------------------------------------------
bool contain(Node* root, Key key) {
if (root == NULL) {
return false;
}
else if (key < root->key) {
contain(root ->left, key);
}
else if (key > root->key) {
contain(root->right, key);
}
else {
return true;
}
}
//-------------------------------------------------------------------查找树------------------------------------------------------------------------
Value* search(Node* node, Key key) {
if (node == NULL) {
return NULL;
}
else if (key < node->key) {
return search(node->left, key);
}
else if (key > node->key) {
return search(node->right, key);
}
else {
return &node->value;
}
}
//--------------------------------------------------------------前序遍历--------------------------------------------------------------------
void preOrder(Node* node){
if (node != NULL) {
cout << node->key << "";
perOrder(node->left);
perOrder(node->right);
}
}
//----------------------------------------------------------------中序遍历------------------------------------------------------------------
void inOrder(Node* node) {
if (node != NULL) {
inOrder(node->left);
cout << node->key << "";
inOrder(node->right);
}
}
//------------------------------------------------------------------后续遍历-------------------------------------------------------------------
void postOrder(Node* node) {
if (node != NULL) {
postOrder(node->left);
postOrder(node->right);
cout << node->key << "";
}
}
//------------------------------------------------------------------析构函数--------------------------------------------------------------
void destory(Node* node) {
if (node != NULL) {
destory(node->left);
destory(node->right);
delete node;
count--;
}
}
};
int main(){
BST<int, int>bst;
cout<<"empty ornot"<<bst.isEmpty()<<endl;
cout << "bst.size()=" << bst.size() << endl;
BST<int,int>bst1;
cout <<bst.insert(bst.insert(NULL, 30, 1), 29, 2)->key << endl;
return 0;
}