数据结构与算法(C++实现)

目录

  • 1.常见算法
    • 1.1最基础的算法-swap(交换)
      • 1.1.1 swap语法:
      • 1.1.2 值传递方式(不成功):
      • 1.1.3 传指针方式
      • 1.1.4 引用的方式
      • 1.1.5 使用宏定义函数
      • 1.1.6 使用std::swap函数(最简便)
    • 1.2 排序算法
      • 1.2.1 冒泡排序
      • 1.2.2 选择排序
      • 1.2.3 插入排序
      • 1.2.4 快速排序
      • 1.2.5 归并排序
    • 1.3 查找算法
      • 1.3.1 顺序查找
      • 1.3.2 折半查找(二分查找)
  • 2.递归
    • 2.1 用递归计算阶乘
    • 2.2 用迭代(循环)计算阶乘
    • 2.3 递归算法-折半查找
    • 2.4 递归算法-permutation(排列组合)
  • 3.栈和队列
    • 3.1 栈
    • 3.2 队列
  • 4.链表
    • 4.1链表基础知识
    • 4.2 链表的插入操作
      • 4.2.1 指定位置的插入
      • 4.2.2 指定位置的删除
    • 4.3链表的构造

1.常见算法

1.1最基础的算法-swap(交换)

1.1.1 swap语法:

int main() {
	int a=1,b=10,temp;
	temp=a;
	a=b;
	b=temp;
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

1.1.2 值传递方式(不成功):

void swap1(int x,int y);

int main() {
	int a,b;
	a=1;
	b=10;
	cout<<"一个不成功的swap方法"<<endl;
	cout<<"a="<<a<<"  b="<<b<<endl;

	swap1(a,b);//此处参数是按值传递的方式,将a和b各拷贝一个传递进去并进行交换
	           //所以发生变化的是拷贝的a和b,输出的a和b未发生改变
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

void swap1(int x,int y)
{
	int temp;
	temp=x;
	x=y;
	y=temp;
}

输出:

一个不成功的swap方法
a=1  b=10
a=1  b=10

1.1.3 传指针方式

void swap1(int *x,int *y);

int main() {
	int a,b;
	a=1;
	b=10;
	cout<<"a="<<a<<"  b="<<b<<endl;
	
	swap1(&a,&b);//因为swap1函数的参数是指针,因此这里需要是地址传递
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

void swap1(int *x,int *y)
{
	int temp;
	temp=*x;
	*x=*y;
	*y=temp;
}

输出:

a=1  b=10
a=10  b=1

1.1.4 引用的方式

void swap1(int &x,int &y);

int main() {
	int a,b;
	a=1;
	b=10;
	cout<<"a="<<a<<"  b="<<b<<endl;
	
	swap1(a,b);//因为引用就是别名,因此可以直接传递
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

void swap1(int &x,int &y)
{
	int temp;
	temp=x;
	x=y;
	y=temp;
}

输出:

a=1  b=10
a=10  b=1

1.1.5 使用宏定义函数

各种类型都可以用,无论 int 或 double 等。

#define SWAP(x,y,t)((t)=(x),(x)=(y),(y)=(t))
int main() {
	int a,b,temp;
	a=1;
	b=10;
	cout<<"a="<<a<<"  b="<<b<<endl;
	
	SWAP(a,b,temp);
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

输出:

a=1  b=10
a=10  b=1

1.1.6 使用std::swap函数(最简便)

各种类型都可以用,无论 int 或 double 等。

int main() {
	int a,b;
	a=1;
	b=10;
	cout<<"a="<<a<<"  b="<<b<<endl;
	
	std::swap(a,b);//C++内已经有这个函数,不用我们再自己写。直接调用即可
	cout<<"a="<<a<<"  b="<<b<<endl;

	system("pause");
	return 0;
}

输出:

a=1  b=10
a=10  b=1

1.2 排序算法

1.2.1 冒泡排序

思想:从左向右扫描数据,选择最大的数据,放在右边;

要点:比较相邻的两个数,如果左边的数大于右边的数,就进行交换。

法1

//函数声明
void bubblesort(int list[],int n); //list是一个数组,n代表数组元素的个数

int main() {
	int a[]={2,4,6,8,0,1,3,5,7,9};
	bubblesort(a,10);

	for(int k=0;k<10;k++)
	{
		cout<<a[k]<<"  ";
	}
	system("pause");
	return 0;
}

void bubblesort(int list[],int n) //函数定义
{
	for(int i=0;i<n-1;i++)
	{
			//如果有10个数据,则一共需要扫描9遍
			//每一遍扫描都是从list[0]开始,
				//第一遍扫描:从list[0]扫到list[9]
				//第二遍扫描:从list[0]到list[8];以此类推
		for(int j=0;j<n-i-1;j++)
		{
			if(list[j]>list[j+1])
				{
					std::swap(list[j],list[j+1]);
				};	
		}
	}
}

输出:

0  1  2  3  4  5  6  7  8  9  

法2

int main() {
	int arr[9]={4,2,8,0,5,7,1,3,9};  //1.创建数组
	cout<<"排序前:";
	for(int i=0;i<9;i++)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
	
	//2.开始排序
	//总共排序轮数=元素个数-1
	for(int i=0;i<9-1;i++)
	{
		//内层循环对比次数=元素个数-当前轮数-1
		for(int j=0;j<9-i-1;j++)
		{
			if(arr[j]>arr[j+1])  //如果第一个数字比第二个数字大,则交换两个数字
			{
				int temp=arr[j];
				arr[j]=arr[j+1];
				arr[j+1]=temp;
			}
		}
	}

	cout<<"排序后:";
	for(int i=0;i<9;i++)
	{
		cout<<arr[i]<<" ";
	}

	system("pause");
	return 0;
}

1.2.2 选择排序

从当前未排序的整数中找一个最小的整数,将它放在已排序的整数列表的后面。

要点:每次扫描只进行一次交换;选则一个最小的,放在左边。

void selectsort(int *a,const int n); //函数声明

int main() {
	int a[]={1,3,5,7,9,0,2,4,6,8};
	selectsort(a,10);
	for(int k=0;k<10;k++)
	{
		cout<<a[k]<<"  ";
	}
	system("pause");
	return 0;
}
void selectsort(int *list,const int n) //函数定义
{
	for(int i=0;i<n;i++)
	{
		int min=i;//把min看做一条毛巾,对数据做记号,暂定认为list[min]最小
		for(int j=i+1;j<n;j++)//第二遍扫描时,从第二个元素即list[1]开始
		{
			if(list[j]<list[min])
				{
					min=j;//扫描中发现list[j]比之前暂定的最小值还要小,就把最小值替换为list[j]
				}
		}
		swap(list[i],list[min]);
	}
}

1.2.3 插入排序

//设房间里有n个人,是无序状态,他们要依次到房间外进行有序排队

void insert( int *a,int n);
int main() {
	int x[]={2,4,6,8,0,1,3,5,7,9};
	insert(x,10);
	for(int i=0;i<10;++i)
	{
		cout<<x[i]<<"  ";
	}
	system("pause");
	return 0;
}

void insert( int *a,int n)
{
	int in,out;//out代表房间内未排队的人,in代表房间外已经排好队的人
	//开始时,out=0这个人已经出去了
	for(out=1;out<n;++out)
	{
		int temp=a[out];
		in=out;
		while(in>0 && a[in-1]>=temp)
		{
			a[in]=a[in-1];
			--in;
		}
		a[in]=temp;
	}
}

输出:

0  1  2  3  4  5  6  7  8  9

1.2.4 快速排序

最流行的排序算法、速度最快的排序算法;

运用递归思路。

1.2.5 归并排序

1.3 查找算法

1.3.1 顺序查找

没有排序的数据,只能进行顺序查找;

顺序查找速度较慢,二分查找速度比较快;

有排序的数据,可以进行顺序查找和二分查找。

//顺序查找

int sequent(int *a,const int n,const int x); //所要查找的数值是x
int main() {
	int m[]={1,3,5,7,9,0,2,4,6,8};
	int result;
	result=sequent(m,10,3);
	if(result==-1)
	{
		cout<<"没找到该数值"<<endl;
	}
	else
	{
		cout<<"所找数值在m["<<result<<"]里"<<endl;
	}
	system("pause");
	return 0;
}
int sequent(int *a,const int n,const int x) 
{
	int i;
	for( i=0;i<n;i++)
	{
		if(a[i]==x)
		{
		   return i;//如果找到x,则返回下标i
		}
	}
	if(i==n)  //如果没找到x,则返回-1
	{
		return -1;		
	}
}

1.3.2 折半查找(二分查找)

二分查找,速度比较快。

int binary(int *a,const int n,const int x); //用指针*a表示数组;n是数组元素个数;x是要查找的数据
int main() {
	int m[]={1,3,5,7,9,0,2,4,6,8};
	int result;
	result=binary(m,10,7);
	if(result==-1)
	{
		cout<<"没找到该数值"<<endl;
	}
	else
	{
		cout<<"所找数值在m["<<result<<"]里"<<endl;
	}
	system("pause");
	return 0;
}
int binary(int *a,const int n,const int x) 
{
	int low,high,mid;//分别表示最小的下标、最大的下标、下标中间值
	low=0; high=n-1;
	while(low<=high)
	{
		mid=(low+high)/2;
		if(a[mid]==x)
		{
		  return mid;
		}
		else if(a[mid]<x)
		{
			low=mid+1;
		}
		else 
		{
			high=mid-1;
		}
	}
	return -1;
}

输出:

所找数值在m[3]

2.递归

递归,就是在运行的过程中调用自己。

一个简单例子:

void a()
{
	cout<<"hello"<<endl;
	a();//自己又调用了自己
}

int main() {
	a();
	system("pause");
	return 0;
}

输出:无限循环hello,陷入死循环
数据结构与算法(C++实现)_第1张图片

2.1 用递归计算阶乘

//5!= 5*4*3*2*1
//5! = 5*4!   4!=4*3!   3!=3*2!   2!=2*1!   1!=1*0!   0!=1
//n! = n*(n-1)!

long int JC(int n)
{
	if(n==0)
	{
		return 1;
	}
	else
	{
		return n*JC(n-1);
	}

}
int main() {
	cout<<JC(5)<<endl; //5的阶乘
	for(int num=0;num<10;num++) //0-9的阶乘
	{
	cout<<num<<"!="<<JC(num)<<endl;
	}
	system("pause");
	return 0;
}

输出:

120
0!=1
1!=1
2!=2
3!=6
4!=24
5!=120
6!=720
7!=5040
8!=40320
9!=362880

2.2 用迭代(循环)计算阶乘

long int JC(int n)
{
	long r=1;
	for(int i=n;i>0;i--)
	{
		r=r*i;
	}
	return r;
}
int main() {
	cout<<JC(5)<<endl; //5的阶乘
	for(int num=0;num<10;num++) //0-9的阶乘
	{
		cout<<num<<"!="<<JC(num)<<endl;
	}
	system("pause");
	return 0;
}

输出:同上

2.3 递归算法-折半查找

int binary(int *a,const int n,const int x); //迭代(循环)方式
int binary1(int *a,const int x,const int low,const int high);//递归方式

int main() {
	int m[]={1,3,5,7,9};
	int result;
	result=binary1(m,7,0,4);//递归方式
	if(result==-1)
	{
		cout<<"没找到该数值"<<endl;
	}
	else
	{
		cout<<"所找数值在m["<<result<<"]里"<<endl;
	}
	system("pause");
	return 0;
}

int binary(int *a,const int n,const int x) //迭代(循环)的方式
{
	int low,high,mid;//分别表示最小的下标、最大的下标、下标中间值
	low=0; high=n-1;
	while(low<=high)
	{
		mid=(low+high)/2;
		if(a[mid]==x)
		{
		  return mid;
		}
		else if(a[mid]<x)
		{
			low=mid+1;
		}
		else 
		{
			high=mid-1;
		}
	}
	return -1;
}

int binary1(int *a,const int x,const int low,const int high)//递归方式
{
	if(low<=high)
	{
		int mid=(low+high)/2;
		if(x<a[mid])
		{
			return binary1(a,x,low,mid-1);
		}
		else if(x>a[mid])
		{
			return binary1(a,x,mid+1,high);
		}
		else
		{
			return mid;
		}
	}
	return -1;
}

输出:

所找数值在m[3]

2.4 递归算法-permutation(排列组合)

//对abc进行排列组合

void permutation( char *p,const int m,const int n)//m和n代表数组元素下标
{
	if(m==n)
	{
		for(int i=0;i<=n;i++)
		{
			cout<<p[i];
		}
		cout<<endl;
	}
	else
	{
		for(int i=m;i<=n;i++)
		{
			swap(p[m],p[i]);
			permutation(p,m+1,n);
			swap(p[m],p[i]);
		}
	}
	//swap(p[0],p[0]);
	//permutation(p,1,2);
	//swap(p[0],p[0]);//以a开头,后面跟着bc的所有排列

	//swap(p[0],p[1]);
	//permutation(p,1,2);
	//swap(p[0],p[1]);//以b开头,后面跟着ac的所有排列

	//swap(p[0],p[2]);
	//permutation(p,1,2);
	//swap(p[0],p[2]);//以c开头,后面跟着ab的所有排列
}

int main() {
	char s[]="abc";
	permutation(s,0,2);
	
	system("pause");
	return 0;
}

数据结构与算法(C++实现)_第2张图片
输出:

abc
acb
bac
bca
cba
cab

3.栈和队列

3.1 栈

3.2 队列

4.链表

4.1链表基础知识

  • 数组是最常用的数据结构,但存在缺点。例如在一个有序数组中插入新数据或删除某数据时,将会使很多数据发生移动,导致效率降低。
  • 链表是第二常用的数据结构。
  • 链表中插入或删除一个数据,只需要修改该数据相邻数据的指针指向即可,不需要移动其他数据的位置。
    数据结构与算法(C++实现)_第3张图片
  • 链表就是表头指针和一串相继链接的结点的总称。
  • 链表每个节点都包含数据域和指针域。
  • 首指针(表头指针) :指向链表的第一个结点的指针变量。 其值为首结点的存储地址。.
  • 表尾结点(最后一个结点)的链域值为空(NULL)
    在这里插入图片描述

4.2 链表的插入操作

4.2.1 指定位置的插入

插在表头:如图,把陈插到表头
数据结构与算法(C++实现)_第4张图片

p->next=head;  //先把陈与张连接,使结点张作为结点陈的后继节点
head=p;            //修改表头指针head,使其指向新的头结点陈

插在表中:如图,把陈插到王和李之间

数据结构与算法(C++实现)_第5张图片

p->next=q->next;   //先把陈与李连接
q->next=p;         //再把王与陈连接

4.2.2 指定位置的删除

删除表头结点

数据结构与算法(C++实现)_第6张图片

q=head;               //为了回收空间,先用q指针记住表头张
head=head->next;      //修改head,使其指向新的表头结点
free(q);              //将空间回归

删除表中结点:删除结点王
数据结构与算法(C++实现)_第7张图片

p=q->next;          //先用p指针记住结点李
//此时结点赵的地址是p->next,也是q->next->next
q->next=p->next;    //将结点王的后继结点修改为结点赵,即删除了结点李   
free(p);            //将空间回收           

链表的特点

  • 结点地址不连续
  • 插入/删除不移动结点,耗时为O(1)
  • 用于动态管理。

4.3链表的构造

构造链表的通用算法

  1. 构造“空链表”
  2. 读入第一个元素值。
  3. 当读入的元素值不是“输入结束标记”时,循环执行步骤4~7。
  4. 申请一个新结点。
  5. 将读入的元值存入新结点的值域。
  6. 将新结点“插在”链表中。
  7. 读入“下一个”元素值,转步骤3。
  8. 构造完毕,返回首指针。

你可能感兴趣的:(c++,算法,数据结构,排序算法)