数据结构复习

基础知识

数据结构的三要素: 逻辑结构、物理结构、数据的运算


逻辑结构:集合、线性结构、树形结构、图形或网状型结构
物理结构(存储结构):顺序存储、链式存储、索引存储、散列存储
数据的运算:施加在数据上的运算包括运算的定义和实现。运算的定义是针对逻辑结构的,指出运算的功能;运算的实现是针对存储结构的,指出运算的具体操作步骤。


集合:结构中的数据元素之间除“同属一个集合”外,别无关系。
线性关系:结构中的数据元素之间只存在一对一的关系。
树形结构:结构中的数据元素存在一对多的关系。
图状或网状结构:结构中的数据元素之间存在多对多的关系。


顺序存储:逻辑上相邻的元素在物理上也相邻。
优点:随机存取、每个元素占用最少的存储空间
缺点:只能使用相邻的存储单元,因此可能产生较多的外部碎片
链式存储:不要求逻辑上相邻的元素在屋里位置上也相邻。
优点:不会出现碎片现象,能充分利用所有存储单元
缺点:只能顺序存储,指针占用空间
索引存储:存储信息的同时,也建立索引表。
优点:可以实现随机存取
缺点:索引表会占用空间,同时修改索引表会花费较多的时间
散列存储:根据元素的关键字直接计算出该元素的存储地址。
优点:检索、增加和删除结点的时间复杂度较低
缺点:散列函数不好,则会出现元素存储单元的冲突,而解决冲突会增加时间和空间的开销


算法的5个重要特性
有穷性:一个算法必须总在执行有穷步之后结束,且每一步都可在有穷时间内完成。
确定性:算法中每条指令必须有确切的含义,对于相同的输入只能得出相同的输出。
可行性:算法中描述的操作都可以通过已经实现的基本运算执行有限次来实现。
输入:一个算法有零个或多个输入
输出:一个算法有一个或多个输出

一个“好"的算法要达到的目标
正确性:算法应能够正确地解决求解问题。
可读性:算法应具有良好的可读性,以帮助人们理解。
健壮性:输入非法数据时,算法能适当地做出反应或进行处理,而不会产生莫名其妙的
输出结果。
效率与低存储量需求:效率是指算法执行的时间,存储量需求是指算法执行过程中所需
要的最大存储空间,这两者都与问题的规模有关。

顺序表

#include<iostream>
#define max 100
//顺序表

typedef struct {
	int data[100];
	int length = 0;
}List;

//方法
// 判空
bool Empty(List L) {
	if (L.length == 0) return true;
	return false;
}
//判满
bool Full(List L) {
	if (L.length == max) return true;
	return false;
}
//插入操作:将e插入到顺序表的第i个位置上
void Insert(List& L, int i, int e) {
	//i越界,则返回
	if (i < 1 || i > max) {
		printf("i越界");
		return;
	}
	
	//如果表满,则返回
	if (Full(L) == true) {
		printf("表满");
		return;
	}
	
	//否则插入
	for (int k = L.length; k >= i; k--) {
		L.data[k] == L.data[k - 1];
	}
	L.data[i - 1] = e;
	L.length++;
}
//删除操作:将顺序表中第i个位置的元素删除,并通过实参e返回
void Delete(List& L, int i, int& e) {
	//表空
	if (Empty(L) == true) {
		printf("表空");
		return;
	}
	
	//i越界
	if (i > L.length) {
		printf("i越界");
		return;
	}

	//否则删除
	e = L.data[i - 1];
	for (int k = i; k < L.length; k++) {
		L.data[k - 1] = L.data[k];
	}
	L.length--;
}
//遍历
void Trace(List L) {
	if (Empty(L)) printf("空的");
	for (int i = 0; i < L.length; i++) {
		printf("%d ", L.data[i]);
	}
}
int main() {
	List L;
	for (int i = 1; i < 10; i++) {
		Insert(L, i, i);
	}
	Trace(L);
	printf("\n");


	int e = 0;
	for (int i = 1; i < 10; i++) {
		Delete(L, 1, e);
	}
	Trace(L);

}

单链表

#include<iostream>

//单链表

typedef struct Node {
	int data;
	struct Node* next;  //此处与上方结构体名相同
}Node,*List;

//初始化
void Init(List& L) {
	L = (List)malloc(sizeof(Node));
	L->next = NULL;
}

//判空
bool Empty(List L) {
	if (L->next == NULL) return true;
	return false;
}

//头插法
void Insert1(List& L, int e) {
	Node* p = (Node*)malloc(sizeof(Node));
	p->data = e;
	p->next = NULL;
	if (Empty(L)) {
		L->next = p;
		return;
	}

	p->next = L->next;
	L->next = p;
}


//尾插法
void Insert2(List& L, int e) {
	Node* p = L;
	//寻找最后一个结点
	while(p->next != NULL) {
		p = p->next;
	}
	
	p->next = (Node*)malloc(sizeof(Node));
	p = p->next;
	p->next = NULL;
	p->data = e;

}

//按位插入
void Insert3(List& L, int k, int e) {
	Node* p = L;
	k--;
	//找到插入位置前一个结点
	while (k--) {
		if (p != NULL)  p = p->next;
		else {
			printf("i越界");
			return;
		}
	}
	//创造新结点
	Node* q = (Node*)malloc(sizeof(Node));
	q->data = e;
	q->next = p->next;
	p->next = q;
}

//删除操作
void Delete(List& L, int k,int &e) {
	if (Empty(L)) return;

	Node* p = L;
	k--;
	//找到插入位置前一个结点
	while (k--) {
		if (p != NULL)  p = p->next;
		else {
			printf("i越界");
			return;
		}
	}
	//越界边界条件
	if (p->next == NULL) return;
	//删除结点
	Node* q = p->next;
	p->next = q->next;
	e = q->data;
	free(q);
	
}

//遍历操作
void Trace(List L) {
	Node* p = L->next;
	while (p != NULL) {
		printf("%d ", p->data);
		p = p->next;
	}
}

int main() {
	List L;
	Init(L);
	//头插法测试:插入12345 ---  54321
	for (int i = 1; i <= 5; i++) {
		Insert1(L, i);
	}
	Trace(L);

	//尾插法测试
	for (int i = 1; i <= 5; i++) {
		Insert2(L, i);
	}

	printf("\n");
	Trace(L);

	//删除测试
	int e;
	for (int i = 1; i <= 5; i++) {
		Delete(L, 1, e);
	}
	printf("\n");
	Trace(L);
}

循环单链表

#include<iostream>

//循环单链表
typedef struct Node {
	int data;
	struct Node* next;
}Node,*List;

//初始化
void init(List& L) {
	L = (List)malloc(sizeof(Node));
	L->next = L;
}

//判空
bool Empty(List& L) {
	if (L->next == L) return true;
	return false;
}
//长度
int Length(List& L) {
	int res = 0;
	Node* p = L->next;
	if (p != L) {
		p = p->next;
		res++;
	}
	return res;
}

//头插法
void Insert1(List& L, int e) {
	Node* p = L;
	Node* q = (Node*)malloc(sizeof(Node));
	q->data = e;
	
	q->next = p->next;
	p->next = q;
}

//按位插入
void Insert2(List& L, int k, int e) {
	Node* p = L;
	Node* q = (Node*)malloc(sizeof(Node));
	q->data = e;

	k--;
	while (k--) {
		p = p->next;
	}
	q->next = p->next;
	p->next = q;
}

//删除操作
void Delete(List& L, int k) {
	if (Empty(L)) return;

	int len = Length(L);
	if (k > len) return;
	
	Node* p = L;
	k--;
	while (k--) {
		p = p->next;
	}
	Node* q = p->next;
	p->next = q->next;
	free(q);
	
}

void Trace(List L) {
	Node* p = L->next;
	while (p != L) {
		printf("%d ", p->data);
		p = p->next;
	}
}

int main() {
	List L;
	init(L);
	//头插法测试
	for (int i = 0; i < 5; i++) {
		Insert1(L, i);
	}
	Trace(L);
	printf("\n");

	//插入操作测试
	for (int i = 6; i < 9; i++) {
		Insert2(L, 1, i);
	}
	Trace(L);
	printf("\n");

	//删除操作
	for (int i = 0; i < 3; i++) {
		Delete(L, 1);
	}
	Trace(L);
	printf("\n");

}

双链表

#include<iostream>

//双链表
typedef struct Dnode {
	int data;
	struct Dnode* prior, * next;
}Dnode,*DLink;

int length(DLink L) {
	Dnode* p = L;
	int res = 0;
	while (p->next != NULL) {
		p = p->next;
		res++;
	}
	return res;
}

bool Empty(DLink L) {
	if (L->next == NULL) return true;
	return false;
}
//插入操作
void Insert(DLink& L, int i, int e) {

	int len = length(L);
	if (len + 1< i || i < 1) return;

	Dnode* p;
	p = L;
	i--;
	while (i--) {
		p = p->next;
	}
	Dnode* q = (Dnode*)malloc(sizeof(Dnode));
	q->data = e;
	q->next = q->prior = NULL;
	

	if (p->next == NULL) {
		p->next = q;
		q->prior = p;
	}
	else {
		p->next->prior = q;
		q->next = p->next;
		p->next = q;
		q->prior = p;
	}

}

//删除操作
void Delete(DLink& L, int i) {

	if (Empty(L)) return;
	if (i > length(L) || i < 1) return;

	Dnode* p;
	p = L;
	i--;
	while (i--) {
		p = p->next;
	}
	Dnode* q = p->next;
	
	p->next = q->next;
	q->next->prior = p;

	free(q);
}

//遍历
void Trace(DLink L) {
	Dnode* p = L->next;
	while (p) {
		printf("%d ", p->data);
		p = p->next;
	}
}


int main() {
	DLink L = (Dnode*)malloc(sizeof(Dnode));
	L->next = NULL;
	L->prior = NULL;

	for (int i = 0; i < 5; i++) {
		Insert(L, i + 1, i);
	}
	Trace(L);


	for (int i = 0; i < 3; i++) {
		Delete(L, 1);
	}

	Trace(L);
}

1.1 单项选择题 1. 数据结构是一门研究非数值计算的程序设计问题中,数据元素的① 、数据信息在计算机中的② 以及一组相关的运算等的课程。 ① A.操作对象   B.计算方法  C.逻辑结构  D.数据映象 ② A.存储结构 B.关系 C.运算 D.算法 2. 数据结构DS(Data Struct)可以被形式地定义为DS=(D,R),其中D是① 的有限集合,R是D上的② 有限集合。 ① A.算法 B.数据元素 C.数据操作 D.数据对象 ② A.操作 B.映象 C.存储 D.关系 3. 在数据结构中,从逻辑上可以把数据结构分成 。 A.动态结构和静态结构 B.紧凑结构和非紧凑结构 C.线性结构和非线性结构 D.内部结构和外部结构 4. 算法分析的目的是① ,算法分析的两个主要方面是② 。 ① A. 找出数据结构的合理性 B. 研究算法中的输入和输出的关系 C. 分析算法的效率以求改进 D. 分析算法的易懂性和文档性 ② A. 空间复杂性和时间复杂性 B. 正确性和简明性 C. 可读性和文档性 D. 数据复杂性和程序复杂性 5. 计算机算法指的是① ,它必具备输入、输出和② 等五个特性。 ① A. 计算方法 B. 排序方法 C. 解决问题的有限运算序列 D. 调度方法 ② A. 可行性、可移植性和可扩充性 B. 可行性、确定性和有穷性 C. 确定性、有穷性和稳定性 D. 易读性、稳定性和安全性 1.2 填空题(将正确的答案填在相应的空中) 1. 数据逻辑结构包括 、 、 和 四种类型,树形结构和图形结构合称为 。 2. 在线性结构中,第一个结点 前驱结点,其余每个结点有且只有 个前驱结点;最后一个结点 后续结点,其余每个结点有且只有 个后续结点。 3. 在树形结构中,树根结点没有 结点,其余每个结点有且只有 个直接前驱结点,叶子结点没有 结点,其余每个结点的直接后续结点可以 。 4. 在图形结构中,每个结点的前驱结点数和后续结点数可以 。 5. 线性结构中元素之间存在 关系,树形结构中元素之间存在 关系,图形结构中元素之间存在 关系。 6. 算法的五个重要特性是__ __ , __ __ , ___ _ , __ __ , _ ___。 7. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0;j<n; j++) A[i][j]=0; 8. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 for (i=0;i<n;i++) for (j=0; j<i; j++) A[i][j]=0; 9. 分析下面算法(程序段),给出最大语句频度 ,该算法的时间复杂度是__ __。 s=0; for (i=0;i<n;i++) for (j=0;j<n;j++) for (k=0;k<n;k++) s=s+B[i][j][k]; sum=s; 10. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 int i=0,s=0; while (s<n) { i++; s+=i; //s=s+i } 11. 分析下面算法(程序段)给出最大语句频度 ,该算法的时间复杂度是__ __。 i=1; while (i<=n) i=i*2;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值