数据结构与算法

数据结构

数据结构(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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值