绪论

本文深入探讨了数据结构与算法的基础知识,包括数据的逻辑结构、存储结构、算法的概念及其特性,介绍了抽象数据类型、时间复杂度分析,并提供了二分查找、最大子列和等经典算法的实现。

1、 绪论

数据的组织和问题的规模有关。

解决问题的方法效率跟空间的利用效率有关

解决问题的效率和算法的巧妙程度有关。

在这里插入图片描述

抽象数据类型(Abstract Data Type)

  • 数据类型
  1. 数据对象集
  2. 数据集合相关联的操作集
  • 抽象 :不依赖具体的实现

编译器写法:

/*
将n(n>1)个整数存放到一维数组R中,设计一个算法,将R中的序列循环左移P(0<p<n)个位置
*/
#include<iostream>
using namespace std;
//A-交换数组,l-数组交换起点位置,r-数组交换终点位置
void Reverse(int A[],int l,int r)
{
	int i,j,temp;
	for(i=l,j=r;i<j;++i,--j)
	{
		temp=A[i];
		A[i]=A[j];
		A[j]=temp;
	}
}
//a-交换数组,n-数组长度,p-交换点
void RCR(int a[],int n,int p)
{
	if(p<=0||p>=n)
	{
		cout<<"error"<<endl;
	}
	else
	{
		Reverse(a,0,p-1);
		Reverse(a,p,n-1);
		Reverse(a,0,n-1);
	}
}
int main()
{
	int L;//交换点
	int i;//
	int R[50];
	int n;//数组长度
	cout<<"交换点位置L=";
	cin>>L;
	cout<<"数组长度n=";
	cin>>n;
	for(i=0;i<n;i++)
	{
		R[i]=i;
	}
	for(i=0;i<n;i++)
	{
		cout<<R[i]<<" ";
	}
	cout<<endl;
	RCR(R,n,L);
	for(i=0;i<n;++i)
	{
		cout<<R[i]<<" ";
	}
	cout<<endl;
	system("pause");
	return 0;
}

纸质写法:

//A-交换数组,l-数组交换起点位置,r-数组交换终点位置
void Reverse(int A[],int l,int r)
{
	int i,j,temp;
	for(i=l,j=r;i<j;++i,--j)
	{
		temp=A[i];
		A[i]=A[j];
		A[j]=temp;
	}
}
//a-交换数组,n-数组长度,p-交换点
void RCR(int a[],int n,int p)
{
	if(p<=0||p>=n)
	{
		cout<<"error"<<endl;
	}
	else
	{
		Reverse(a,0,p-1);
		Reverse(a,p,n-1);
		Reverse(a,0,n-1);
	}
}

1.1 结点的构造

先定义一个结点的结构类型,然后用这个结构型制作一个结点。

1.1.1 定义结点的结构类型

凡是结构型(假设名为a)的内部都有这样的指针型(假设名为b),即b是用来存放和a类型相同的结构体变量地址的指针型(结点a的指针next,next所指的结点b与结点a是属于同一结构类型的),则在定义a的typedef struct 语句之后都要加上a这个结构体的名字。

//结构体正常定义
typedef struct 
{
    int a;
    char b;
}TypeA;

结构型结点-链表

typedef struct Node 
{
    int data;
    struct Node *next;//指向Node型变量的指针
}Node;

结构型结点-二叉树

typedef struct BTNode
{
    int data;
    struct BTNode *lchild;//l
    struct BTNode *rchild;//指向右子结点指针}BTNode;

1.1.2 制作结点

1. BTNode BT;
2. BTNode *BT;//定义一个结点指针
BT=(BTNode*)malloc(sizeof(BTNode));用malloc申请一个结点内存空间,最后然指针BT指向这片内存空间
//动态申请数组空间方法 
int *p;
p=(int *)malloc(n*sizeof(int));

1.2 函数

1.2.1 传入函数的参数会改变、

void f(int *&x)//指针型变量在函数体中需要改变的写法
{
    ++x;
}
void g(Slist &s,int x)//s本身发生变化,采用引用型
{
}
void q(Node *c ,int x)//c是一个指向一个链表表头的指针,指针自身不变,因此不需要采用引用型

1.3 时间复杂度分析

将算法中的基本操作的执行次数作为算法时间复杂度的度量。一般按照使基本操作执行次数最多的输入来计算时间复杂度

O(1)≤O(log2(n))≤O(n)≤O(nlog2(n))≤O(n2)≤…≤O(nk)≤O(2^n) n为问题的规模

1.3 数据结构的基本概念

数据 对客观事物的符号表示

数据元素 数据的基本单元,计算机程序中将其作为一个整体进行考虑和处理。一个数据元素可由若干数据项组成。e.g. 一本书的目录为一个数据元素,每一个目为一个数据项

数据项 数据结构中最基本单元,其表示称为数据域

数据对象 性质相同的数据元素的集合,是数据的一个子集。

数据结构 相互存在一种或多种特定关系的数据元素的集合,包括:逻辑结构、存储结构和对数据的运算。

1.3.1 数据的逻辑结构

对数据之间关系的描述,主要有线性结构和非线性结构。

线性结构指数据元素之间存在“一对一”的线性关系的数据结构。

非线性结构指其结点存在“一对多”的关系,可分为树形结构和图形结构

1.3.2 数据的存储结构

包括数据元素的表示和关系的表示。当数据元素是由若干数据项构成时,数据项的表示称为数据域。e.g. 一个链表结点包含值域和指针域。

4种方式:顺序储存方法,链式存储方法,索引存储方法、散列存储方法。

1.4 算法的基本概念

由基本运算及规定的运算顺序所构成的完整的解题步骤。

特点:有穷性,确定性,有输入输出,可行性(有限次)

1.5 练习

1.5.1 二分查找

Position BinarySearch( List L, ElementType X )
{
	Position p=NotFound;
	int left=1,right=L->Last, mid;
	if(X<L->Data[left]||X>L->Data[right])
		return p;
	while(left<=right)
	{
		if(X==L->Data[left])
	{
		p=left;
			return p;
	}
	else if(X ==L->Data[right])
	{
		p=right;
		return p;
	}
		//当前查找区间为[left,right]
		mid=left+(right-left)/2;
		/*
		使用(low+high)/2会有整数溢出的问题(问题会出现在当low+high的结果
		大于表达式结果类型所能表示的最大值时,这样,产生溢出后再/2是不会
		产生正确结果的,而low+((high-low)/2)不存在这个问题
		*/
		if(L->Data[mid]==X) 
		{
			p=mid;
				return p;
		}

		else if(L->Data[mid]>X)//在[left,mid-1]查找
		{
			right=mid-1;
		}
		else if(L->Data[mid]<X)//在[mid+1,right]查找
		{
			left=mid+1;
		}
	}
	return p;
}

1.5.2 最大子列

牛客网

最大子列和问题

csdn最大子列和问题

 int MaxSubSum(int a[],int N)
 {
	 int MaxSub=0;
	 for(int i=0;i<N;++i)
	 {
		 int sum=0;
		 for(int j=i;j<N;j++)
         {
             sum+=a[j];
             if(sum>MaxSub)
                 MaxSub=sum;
         }
	 }
	 return MaxSub;
 }
 int MaxSubSum(int a[],int N)
 {
	 int MaxSub=0,sum=0;
	 for(int i=0;i<N;++i)
	 {
		 sum+=a[i];
		 if(sum>MaxSub)
			 MaxSub=sum;
		 else if(sum<0)
			 sum=0;
	 }
	 return MaxSub;
 }
#include<iostream>
using namespace std;
const int maxN=1e5;
 int a[maxN],N;//列数
int solve(int left,int right)
{
	/*分而治之的方法求List[left]到List[right]的最大子列和*/
	if(left==right)
	{
		/*递归的终止条件,子列只有一个数字*/
		return a[left]>0?a[left]:0;
	}
	/*下面是"分"的过程*/
	int mid=left+(right-left)/2;/*中分店*/
	/*递归求得两边子列最大和*/
	int lans=solve(left,mid);
	int rans=solve(mid+1,right);
	/*求跨分界线的最大子列和*/
	int sum=0,lmax=a[mid],rmax=a[mid+1];
	for(int i=mid;i>=left;--i)
	{/*从中线向左扫描*/
		sum+=a[i];
		if(sum>lmax) lmax=sum;
	}
	sum=0;
	for(int i=mid+1;i<=right;++i)
	{/*从中线向右扫描*/
		sum+=a[i];
		if(sum>rmax) rmax=sum;
	}
	int ans=lmax+rmax;
	/*比较*/
	ans=(lans>rans)?(lans>ans?lans:ans):(rans>ans?rans:ans);
	return ans;
}
int main()
{
	 
	 int p;
	 int sum;
	 cin>>N;
	 for(int i=0;i<N;++i)
	 {
		 cin>>p;
		 a[i]=p;
	 }
	 int ans;
	 cout<<solve(0,N-1);
	 return 0;

### 数据结构绪论的基本概念 #### 什么是数据结构? 数据结构是指相互之间存在一种或多种特定关系的数据元素的集合[^1]。它不仅关注单个数据元素本身,还研究这些元素之间的关联方式。 #### 数据的相关术语 - **数据**:描述客观事物的符号,是计算机能够操作的对象,包括但不限于数值、字符、声音、图像和视频等[^2]。 - **数据元素**:构成数据的基本单位,具有一定的实际意义,在计算中常作为一个整体被处理,也称为记录。 - **数据项**:数据不可再分的最小单元。 - **数据对象**:由性质相同的若干数据元素组成的集合,它是数据的一个子集。 #### 数据结构的分类 数据结构主要分为两大类: 1. **逻辑结构**:指数据元素之间的逻辑关系,而不考虑其在计算机中的存储形式。常见的逻辑结构有线性结构(如数组、链表)、树形结构、图形结构以及集合结构。 2. **物理结构**:即存储结构,指的是数据及其关系在计算机内存中的具体表示方法。主要包括顺序存储结构和链接存储结构两种基本形式[^2]。 #### 学习的意义 理解并掌握数据结构的概念对于程序设计至关重要。正如所提到,“定义是抽象的,但注重定义是学习的一条捷径。”通过深入探讨各种数据结构的特点与应用场合,可以更高效地解决复杂问题。 ```python class Node: def __init__(self, data=None): self.data = data self.next = None def create_linked_list(elements): head = Node() current = head for element in elements: node = Node(element) current.next = node current = node return head.next # 创建一个简单的链表实例 linked_list_head = create_linked_list([10, 20, 30]) ``` 以上代码片段展示了如何创建一个简单的链式列表,这是典型的线性数据结构之一。 #### 总结 综上所述,数据结构不仅是理论知识的学习重点,也是实践技能提升的关键领域。通过对不同类型的结构进行分析比较,有助于开发人员选择最适合解决问题的具体实现方案。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值