数据结构专用
0、建模的本质:从问题中抽取关键的对象,找出这些对象之间的关系,以合适的语言或符号加以描述; 问题的种类:数值型,非数值型 ;
逻辑结构:图结构,树结构,线性结构,集合结构 ;物理结构:数据元素及关系在计算机内存中的存储方式
1、将元素“42,30,74,56,15,60”依次插入开始为空的检索树,那么不成功查找的平均查找长度为 3 (21/7),不成功的结点为7,2×2+3×3+2×4=21;
2、具有5层结点的AVL树至少有 12 个结点
3、时间复杂度不受数据初始状态影响而恒为O(nlogn)的是 堆排序
4、高为h的m元树(m≥2, h≥1)中结点总数n<=(mh-1)/(m-1)
5、已知一棵二叉树的先序序列是A,B,C,D,E,F,G,和整数序列3,0,0,6,0,0,0。其中,整数序列中的第i个数,表示先序序列第i个结点的右儿子在先序序列中的序号(序号从1编起,0表示无右儿子)。请问此二叉树中以结点D为根的子树的结点个数为 4
6、就排序算法所用的辅助空间而言,堆排序、快速排序、归并排序的关系是,堆排序<快速排序<归并排序
7、二维数组A的元素都是6个字符组成的串,行下标i的范围从0到8,列下标j的范围从1到10,则A的第8列和第5行共占108个字节,第8列9个元素,第5行10个元素,共9+10-1个元素,18×6==108;
8、设一棵二叉树的结点个数为18,则它的高度至少为 5,2h-1,24-1==15
9、在文件“局部有序”或文件长度较小的情况下,最佳内部排序的方法是,直接插入排序;
10、对关键字序列(56,23,78,92,88,67,19,34)进行增量为3的一趟希尔排序的结果为(19,23,67,56,34,78,92,88);56,92,19;23,88,34;78,67;增量为3的,三组分别排序;一趟后,结果19,23,67,56,34,78,92,88;
11、采用排序算法对n个元素进行排序,其排序趟数肯定为n-1趟的排序方法是,直接选择和插入 ;A 直接插入和快速排序,B 冒泡和快速排序,C 直接选择和堆排序,D 直接选择和插入排序
12、设有5000个待排序的记录关键字,如果需要用最快的方法选出其中最小的10个记录关键字,则用下列( 堆排序 )方法可以达到此目的,A 快速排序,B 直接选择排序,C 归并排序,D 堆排序;
13、在对n个元素进行选择排序的过程中,第i趟需从 n-i+1 个元素中选出最小值元素;第i趟,是从1开始计算的,没有第0趟,第一趟即 n-1+1,从n个元素中选择;
14、对于简单无向图而言,一条回路至少含有3条边;对于无向加权图而言,其最小生成树有可能不存在,但如果存在的话通常是不唯一的;n个顶点的有向图中,顶点的最大度数等于2(n-1);对含有k个连通分量的无向图进行先深搜索时,主控函数中需要调用递归的搜索函数dfs k 次;对于无向图的邻接矩阵,第i行上的非零元素个数和第i列的非零元素个数一定相等;
15、对于n个顶点,m条边的无向图G,若m≥n,则G中必含回路
16、n个顶点的有向图中,顶点的最大度数等于2(n-1),出度n-1,入度n-1
17、在具有n个顶点的图G中,若最小生成树不唯一,则G的边数一定大于n-1;生成树有n个顶点和n-1条边。最小生成树是权值之和最小的那棵生成树。若最小生成树不唯一,一定是有权值相等的边,但未必是权值最小的边相等。最小生成树的代价一定相等。当然,G的边数一定大于n-1,否则,就只有一棵生成树了。
18、在有向图的邻接表存储结构中,顶点v在链表中出现的次数是顶点v的入度;对于有向图,vi的邻接表中每个表结点都对应于以vi为始点射出的一条边。因此,将有向图的邻接表称为出边表。所以顶点V在链表中出现的次数是顶点V的入度
19、一个有向图,共有n条弧,则所有顶点的度的总和为2n
20、如果含有n个顶点的图形成一个环,则它有 n 棵生成树;n个顶点形成的环有n条边,若得到生成树只需要删除这n条边中的任意一条即可,所以得到n棵生成树
21、一个关键活动提前完成,只能让这条关键路径变成非关键路径。当关键路径不止一条的时候,单单提高一条关键路径上关键活动的速度,是不能缩短整个工程工期的。所以,并不是网中任何一个关键活动提前完成,整个工程都能提前完成。但如果网中任何一个关键活动延期完成,整个工程一定延期。
22、连通分量是 无向图 的极大连通子图
23、一个具有n个顶点的有向图中,要连通全部顶点至少需要 n 条弧
24、判断一个有向图是否存在回路,可以用深度优先遍历算法 ,当有向图中无回路时,从某顶点出发进行深度优先遍历时,出栈的顺序(退出DFSTraverse算法)即为逆向的拓扑序列。
25、若一个无向图以顶点V1为起点进行深度优先遍历,所得的遍历序列唯一,则可以唯一确定该图
26、图的路径,由邻接顶点构成的序列
27、带权有向图G用邻域矩阵A存储,则顶点i的入度等于A中,第i列非∞且非零的元素个数
28、对于含有n个顶点的带权连通图,它的最小生成树是指图中任意一个,由n个顶点构成的边的权值之和最小的连通子图
29、无向连通图,所有顶点的度之和为偶数
30、最小生成树的代价唯一
31、具有12个关键字的有序表,折半查找的平均查找长度 37/12,将12个数画成完全二叉树,第一层有1个、第二次2个、第三层4个,第四层只有5个。二分查找时:第一层需要比较1次,第二两个数,每个比较2次,第三层四个数,每个比较3次,第四层五个数,每个比较4次,则平均查找长度即为37/12;
32、如果要求用线性表既能较快地查找,又能适应动态变化的要求,则可采用 分块查找 方法;分块查找是将表分成若干块,分块的原则是数据元素的关键字在块与块之间是有序的,而块内元素的关键字是无序的,其可以适应动态变化的要求;
33、简单选择排序和堆排序性能都受初始序列顺序的影响,是错的
34、在对n个关键字进行直接选择排序的过程中,每一趟都要从无序区选出最小关键字元素,则在进行第i趟排序之前,无序区中关键字元素的个数为 n-i+1
35、将两个各有n个元素的有序表合并成一个有序表,其最少的比较次数为 n
36、在对n个元素进行快速排序的过程中,最坏情况下需要进行 n-1 趟
37、通过先序遍历可以删除二叉树中所有的叶子结点。
38、完全二叉树,可由其先序序列唯一确定,完全二叉树,可由其中序序列唯一确定,满二叉树,可由其后序序列唯一确定
39、含3个结点的普通树的树形共有2种
40、假定一棵三叉树的结点数为50,则它的最小高度为5: 结点数相同而高度最小的三叉树是满三叉树或完全三叉树(深度为h的三叉树,若前面h-1层是满的,只有第h层从右边连续缺若干个结点的三叉树称为完全三叉树)。根据完全二叉树的性质4 (即具有n个结点的完全二叉树,其深度h=[log2n]+1),可推得三叉树的相应性质,即具有n个结点的完全三叉树,其深度h = [log3n]+1。故具有50个结点的三叉树,其最小高度为[log350]+1=5。
41、在哈夫曼树中,若编码长度只允许小于等于4,则除了已确定两个字符的编码为0和10外,还可以最多对 4 个字符进行编码。1100 1101 1110 1111
42、判断:一棵二叉树中,中序遍历序列的最后一个结点,必定是该二叉树前序遍历的最后一个结点。(错,右子树有左子树不一样)
43、具有n片叶子的完全二叉树共有2个
44、给定有n个结点的向量,建立一个有序单链表的时间复杂度 O(n^2)
45、在一个单链表HL中,若要向表头插入一个由指针p指向的结点,则执行p->next = HL; HL = p;
46、将两个各有n个元素的有序表归并成一个有序表,在最坏的情况下,其比较次数是 2n-1
47、对顺序存储的线性表,设其长度为n,在任何位置上插入或删除操作都是等概率的。插入一个元素时平均要移动表中的 n/2 个元素。
48、在一个长度为n的线性表中顺序查找值为x的元素时,查找时的平均查找长度(即x同元素的平均比较次数,假定查找每个元素的概率都相等)为(n+)/2
49、单链表,删除指针指向的结点,通过复制后继结点的数据的方式,实现删除:设指针变量p指向单链表中结点A,若删除单链表中结点A,则需要修改指针的操作序列为:q=p->next;p->data=q->data;p->next=q->next;free(q);
50、m行n列的矩阵,非零项个数为t, t / (m*n) <= 0.3 的矩阵为稀疏矩阵。
51、三种特殊矩阵:上三角,下三角矩阵,带状矩阵(采取顺序存储);稀疏矩阵(采取三元组顺序存储,十字链表链式存储,都不可随机访问)。
52、下三角矩阵存储元素地址计算公式 :loc(i,j) = loc(1,1) + ( i*(i-1)/2 + j -1 )*size (等差数列)
53、上三角矩阵存储元素地址计算公式 :loc(i,j) = loc(1,1) + ( (i-1)*(2*n-i+2)/2 + j -i )*size,(等差数列)n为矩阵列数
54、带状矩阵存储元素地址计算公式:loc(i,j) = loc(1,1) + ( 2+3*(i-2) + j -i+1)*size,
55、十字链表定义(行链表,列链表组成)
//十字链表结点定义
typedef struct OLNode
{
int row,col; //行,列
ElemType value;
struct OLNode *right, *down;//行列指针
}OLNode, *OLink;
//十字链表定义
typedef struct
{
OLink *row_head, *col_head; //行列链表头指针数组
int m, n; //m行,n列
}CrossList;
56、算法原地工作是指算法所需的辅助空间是常量 ,空间复杂度O(1),表示所需空间为常量,并且与n无关
57、数据结构:带结构的数据元素。
58、堆是完全二叉树,是有序的,存储可以用数组连续存储
59、https://blog.csdn.net/shuiyixin/article/category/7555856
60、迭代,逻辑上,多次使用同一算法。
61、排序
#include<stdio.h>
#define N 50
#include<stdlib.h>
#define INSERT_SROT 0
#define SHELL_SROT 1
#define BUBBLE_SROT 2
#define QUICK_SORT 3
#define SIMPLE_SELECTION_SROT 4
#define HEAP_SORT 5
#define MERGING_SROT 6
#define MOVING_COUNT 0
#define COMPARING_COUNT 1
int result[7][2];
void InsertionSort(int * pData, int n)
{
int temp;
for (int i = 1; i < n; i++)
{
temp = pData[i];
for (int j = i - 1; j >= 0 && temp < pData[j]; j--)
{
pData[j+1]= pData[j];
result[INSERT_SROT][MOVING_COUNT]++;
result[INSERT_SROT][COMPARING_COUNT]++;
}
pData[i+ 1] = temp;
result[INSERT_SROT][MOVING_COUNT]++;
}
}
void ShellSort(int * pData, int n, int delta)
{
int temp;
for (int i = 1; i < n; i = i + delta)
{
temp = pData[i];
for (int j = i - delta; j >= 0 && temp < pData[j]; j = j - delta)
{
result[SHELL_SROT][MOVING_COUNT]++;
result[SHELL_SROT][COMPARING_COUNT]++;
pData[j + delta] = pData[j];
}
pData[i + delta] = temp;
result[SHELL_SROT][MOVING_COUNT]++;
}
}
void Shell(int * pData, int n)
{
int k = 4;
while(k>=1)
{
ShellSort(pData, n, k);
k = k / 2;
}
}
void BubbleSort(int a[], int n)
{
int temp;
for (int i = 1; i <= n - 1; i++)
{
for (int j = 1; j <= n - i; j++)
{
result[BUBBLE_SROT][COMPARING_COUNT]++;
if (a[j - 1] > a[j])
{
temp = a[j];
a[j] = a[j - 1];
a[j - 1] = temp;
}
result[BUBBLE_SROT][MOVING_COUNT] += 3;
}
}
}
int Parition(int a[], int i, int j)
{
int temp = a[j];
while (i < j)
{
while (a[j] >= temp && i < j)
{
j--;
result[QUICK_SORT][COMPARING_COUNT]++;
}
if (i < j)
{
a[i++] = a[j];
result[QUICK_SORT][MOVING_COUNT]++;
}
while (a[i] <= temp && i < j)
{
i++;
result[QUICK_SORT][COMPARING_COUNT]++;
}
while (a[i] <= temp && i < j)
{
i++;
result[QUICK_SORT][COMPARING_COUNT]++;
}
if (i < j)
{
a[j--] = a[i];
result[QUICK_SORT][MOVING_COUNT]++;
}
}
a[i] = temp;
result[QUICK_SORT][MOVING_COUNT]++;
return i;
}
void QuickSort(int a[], int i, int j)
{
int k;
if (i < j)
{
k = Parition(a, i, j);
QuickSort(a, i, k - 1);
QuickSort(a, k + 1, j);
}
}
void SimpleSelectionSort(int a[], int n)
{
int min;
int temp;
for (int i = 0; i < n - 1; i++)
{
min = i;
for (int j = i + 1; j < n; j++)
if (a[j] < a[min])
{
min = j;
result[SIMPLE_SELECTION_SROT][COMPARING_COUNT]++;
}
temp = a[i];
a[i] = a[min];
a[min] = temp;
result[SIMPLE_SELECTION_SROT][MOVING_COUNT] += 3;
}
}
#define LeftChild(i)(2*(i)+1)
void BuildDown(int a[], int n, int rootIndex)
{
int root = a[rootIndex];
int childIndex = LeftChild(rootIndex);
while (childIndex < n)
{
childIndex++;
result[HEAP_SORT][COMPARING_COUNT]++;
if (root < a[childIndex])
{
a[rootIndex] = a[childIndex];
result[HEAP_SORT][COMPARING_COUNT]++;
rootIndex = childIndex;
childIndex = LeftChild(rootIndex);
}
else
break;
}
a[rootIndex] = root;
}
void HeapSort(int a[], int n)
{
int temp;
for (int rootIndex = (n - 2) / 2; rootIndex >= 0; rootIndex--)
BuildDown(a, n, rootIndex);
for (int i = n - 1; i >= 0; i--)
{
temp = a[0];
a[0] = a[i];
a[i] = temp;
result[HEAP_SORT][COMPARING_COUNT] += 3;
BuildDown(a, i, 0);
}
}
void Merge(int a[],int s1,int e1,int s2,int e2,int b[])
{
int k = s1;
int i = s1;
while ((s1 <= e1) && (s2 <= e2))
{
result[MERGING_SROT][COMPARING_COUNT]++;
if (a[s1] <= a[s2])
{
b[k++] = a[s1++];
result[MERGING_SROT][MOVING_COUNT]++;
}
else
{
b[k++] = a[s2++];
result[MERGING_SROT][MOVING_COUNT]++;
}
}
while (s1<=e1)
{
b[k++] = a[s1++];
result[MERGING_SROT][MOVING_COUNT]++;
}
while (s2 <= e2)
{
b[k++] = a[s2++];
result[MERGING_SROT][MOVING_COUNT]++;
}
k --;
while (k>= i)
{
a[k] = b[k];
k--;
result[MERGING_SROT][MOVING_COUNT]++;
}
}
void MergeSort(int a[], int i, int j, int b[])
{
int k;
if (i < j)
{
k = (i + j) / 2;
MergeSort(a, i, k, b);
MergeSort(a, k + 1, j, b);
Merge(a, i, k, k + 1, j, b);
}
}
void Generate_Random(int a[], int length, int max, int min)
{
for (int i = 0; i < length; i++)
{
a[i] = rand() % (max - min + 1);
a[i] += min;
}
}
int data[N], back[N];
int main()
{
int i, j;
for (i = 0; i < 7; i++)
for (j = 0; j < 2; j++)
result[i][j] = 0;
printf("\t\t比较次数\t移动次数\t比较次数(有序)\t移动次数(有序)\n");
Generate_Random(data, 50, 10, 1);
InsertionSort(data, 50);
Generate_Random(data, 50, 10, 1);
Shell(data, 50);
Generate_Random(data, 50, 10, 1);
BubbleSort(data, 50);
Generate_Random(data, 50, 10, 1);
QuickSort(data, 0, 49);
Generate_Random(data, 50, 10, 1);
SimpleSelectionSort(data, 50);
Generate_Random(data, 50, 10, 1);
HeapSort(data, 50);
Generate_Random(data, 50, 10, 1);
MergeSort(data, 0, 49, back);
int result_back[7][2];
for (i = 0; i < 7; i++)
for (j = 0; j < 2; j++)
{
result_back[i][j] = result[i][j];
result[i][j] = 0;
}
InsertionSort(data, 50);
Shell(data, 50);
BubbleSort(data, 50);
QuickSort(data, 0, 49);
SimpleSelectionSort(data, 50);
HeapSort(data, 50);
MergeSort(data, 0, 49, back);
const char*name[7] = { "插入排序","希尔排序","冒泡排序","快速排序","简单排序","堆排序","归并排序" };
for (i = 0; i < 7; i++)
{
printf("%-10s", name[i]);
for (j = 0; j < 2; j++)
printf("\t%d\t", result_back[i][j]);
for (j = 0; j < 2; j++)
printf("\t%d\t", result[i][j]);
printf("\n");
}
return 0;
}
62、二叉排序树
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
int ASL[4] = {0}; //Average Search Length 查找成功时的平均查找长度
#define SEQ_SEARCH 0 //顺序查找 下标
#define BINARY_SEARCH 1 //二分查找 下标
#define BST_SEARCH 2 //二分查找树 下标
#define BALANCE_SEARCH 3 //平衡查找树 下标
typedef struct Node //定义树结点
{
int key;
struct Node *pLeft;
struct Node *pRight;
int bf; //Balance Factor 平衡因子
} Node;
//1、SeqSearch 顺序查找
int SeqSearch(int a[], int length, int key)
{
for (int i = 0; i < length; i++)
{
ASL[SEQ_SEARCH]++;
if (a[i] == key)
return i;
}
return -1;
}
//2、Binary_Search 二分查找
int Binary_Search(int a[], int n, int key)
{
int l = 0;
int h = n - 1;
int m;
while (l <= h)
{
m = (l + h) / 2;
ASL[BINARY_SEARCH]++;
if (key == a[m])return m;
ASL[BINARY_SEARCH]++;
if (key < a[m])
h = m - 1;
else
l = m + 1;
}
return-1;
}
//3、SearchBST 二分查找树 ( 查找并插入 )
int SearchBST(Node *pRoot, int key, Node ** pKeyNode, Node ** pParentNode)
{
*pKeyNode = pRoot;
*pParentNode = NULL;
while (*pKeyNode)
{
if (key > (*pKeyNode)->key)
{
ASL[BST_SEARCH]++;
*pParentNode = *pKeyNode;
*pKeyNode = (*pKeyNode)->pRight;
}
else if
(key <(*pKeyNode)->key)
{
ASL[BST_SEARCH]++;
*pParentNode = *pKeyNode;
*pKeyNode = (*pKeyNode)->pLeft;
}
else
{
return 1;
}
}
return 0;
}
//*3、 SearchBST 二分查找树 ( 纯查找 )
int SearchBST(Node*pRoot, int key)
{
int found = 0;
Node *pKeyNode = pRoot;
while (pKeyNode)
{
if (key > pKeyNode->key)
{
ASL[BST_SEARCH]++;
pKeyNode = pKeyNode->pRight;
}
else if (key < pKeyNode->key)
{
ASL[BST_SEARCH]++;
pKeyNode = pKeyNode->pLeft;
}
else
{
return 1;
}
}
return 0;
}
//4、SearchBalanceBST 平衡查找树
int SearchBalanceBST(Node*pRoot,int key)
{
int found = 0;
Node *pKeyNode = pRoot;
while (pKeyNode)
{
if (key > pKeyNode->key)
{
ASL[BALANCE_SEARCH]++;
pKeyNode = pKeyNode->pRight;
}
else if (key < pKeyNode->key)
{
ASL[BALANCE_SEARCH]++;
pKeyNode = pKeyNode->pLeft;
}
else
{
return 1;
}
}
return 0;
}
//二分查找树插入结点
int InsertBST(Node ** pRoot, int key)
{
Node * pKeyNode = NULL;
Node * pParentNode = NULL;
if (SearchBST(*pRoot, key, &pKeyNode, &pParentNode))
return 0;
Node *pNewNode = (Node*)malloc(sizeof(Node));
pNewNode->key = key;
pNewNode->pLeft = pNewNode->pRight = NULL;
if (*pRoot == NULL)(*pRoot) = pNewNode;
else if (key < pParentNode->key)
pParentNode->pLeft = pNewNode;
else pParentNode->pRight = pNewNode;
return 1;
}
//二分平衡树旋转操作
void RightRotate(Node ** pNode)
{
Node * pAxis = (*pNode)->pLeft;
(*pNode)->pLeft = pAxis->pRight;
pAxis->pRight = *pNode;
*pNode = pAxis;
}
void LeftRotate(Node ** pNode)
{
Node * pAxis = (*pNode)->pRight;
(*pNode)->pRight = pAxis->pLeft;
pAxis->pLeft= *pNode;
*pNode = pAxis;
}
void LL_LR_Balance(Node ** pNode)
{
Node * pLeft = (*pNode)->pLeft;
switch (pLeft->bf)
{
case 1: //RightRotate
(*pNode)->bf = pLeft->bf = 0;
RightRotate(pNode);
break;
case -1: //LeftRotate / RightRotate
Node*pRight = pLeft->pRight;
switch (pRight->bf)
{
case 0:
(*pNode)->bf = pLeft->bf = 0;
break;
case 1:
pRight->bf= pLeft->bf = 0;
(*pNode)->bf = -1;
case -1:
(*pNode)->bf = pRight->bf = 0;
pLeft->bf = 1;
break;
}
LeftRotate(&(*pNode)->pLeft);
RightRotate(pNode);
break;
}
}
void RR_RL_Balance(Node ** pNode)
{
Node *pRight = (*pNode)->pRight;
switch (pRight->bf)
{
case -1: //LeftRotate
(*pNode)->bf = pRight->bf = 0;
LeftRotate(pNode);
break;
case 1: //RightRotate/LeftRotate
Node*pLeft = pRight->pLeft;
switch (pLeft->bf)
{
case 0:
(*pNode)->bf = pRight->bf = 0;
break;
case 1:
(*pNode)->bf = pLeft->bf = 0;
pRight->bf = -1;
break;
case -1:
pRight->bf = pLeft->bf = 0;
(*pNode)->bf = 1;
break;
}
RightRotate(&(*pNode)->pRight);
LeftRotate(pNode);
break;
}
}
//二分平衡树插入
int InsertBalanceBST(Node ** pRoot, int key, int * chain)
{
if ((*pRoot) == NULL) //找到位置插入
{
*pRoot=(Node*)malloc(sizeof(Node));
(*pRoot)->bf = 0;
(*pRoot)->pLeft = (*pRoot)->pRight = NULL;
(*pRoot)->key = key;
*chain = 1;
}
else //查找插入位置
{
if (key == (*pRoot)->key)
{
*chain = 0;
return 0;
}
if (key < (*pRoot)->key) //LL_LR_Balance
{
if (!InsertBalanceBST(&(*pRoot)->pLeft, key, chain))return 0;
if (*chain)
{
switch ((*pRoot)->bf)
{
case 0:
(*pRoot)->bf = 1;
*chain = 1;
break;
case 1:
LL_LR_Balance(pRoot);
*chain = 0;
break;
case -1:
(*pRoot)->bf = 0;
*chain = false;
break;
}
}
}
else //RR_RL_Balance
{
if (!InsertBalanceBST(&(*pRoot)->pRight, key, chain))
return 0;
if (*chain)
{
switch ((*pRoot)->bf)
{
case 0:
(*pRoot)->bf = -1;
*chain = true;
break;
case 1:
(*pRoot)->bf = 0;
*chain = false;
break;
case -1:
RR_RL_Balance(pRoot);
*chain = false;
break;
}
}
}
}
return 1;
}
//随机值函数
void Generate_Random(int a[], int length, int max, int min)
{
for (int i = 0; i < length; i++)
{
a[i] = rand() % (max - min + 1);
a[i] += min;
}
}
//中序打印树
void InorderTraversal( Node* BT )
{
if(BT)
{
InorderTraversal(BT->pLeft);
printf(" %d",BT->key);
InorderTraversal(BT->pRight);
}
}
//打印数组
void PrintArrayData(int data[]){
int i;
for(i=0; i<50; i++)
{
printf(" %d", data[i]);
}
printf("\n");
}
int main( )
{
int data[50];
int back[2];
int temp;
int i;
//------------------------------------------
for (i = 0; i < 50; i++) //有序数据
data[i] = i;
for (i = 0; i < 5000; i++)
{
Generate_Random(back, 2, 49, 1);
temp = data[back[0]];
data[back[0]] = data[back[1]];
data[back[1]] = temp;
}
//PrintArrayData(data); //数据已经打乱
Node * pTree = NULL;
Node * pBTree = NULL;
int chain = 0;
for (i = 0; i < 50; i++) //插入打乱的数据到二叉树
{
InsertBST(&pTree, data[i]); //二叉树
InsertBalanceBST(&pBTree, data[i], &chain); //平衡二叉树
}
/* InorderTraversal(pTree); printf("\n");
InorderTraversal(pBTree); printf("\n"); */
//---------------------------------------------
for (i = 0; i < 50; i++) //因为二分查找必须有序
data[i] = i;
for (i = 0; i < 4; i++)
ASL[i] = 0;
for (i = 49; i >= 0; i--)
{
SeqSearch(data, 50, data[i]);
Binary_Search(data, 50, data[i]);
SearchBST(pTree, data[i]);
SearchBalanceBST(pBTree, data[i]);
}
const char *name1[] = { "顺序查找","二分查找","二分查找树","平衡查找树" };
for (i = 0; i < 4; i++)
{
printf("\t%s \t%f\n", name1[i], (float)ASL[i] / 50.0);
}
return 0;
}
63、散列表冲突处理方法:开放地址法(线性探测,平方探测,双散列),分离链接法。线性探测容易产生聚集,平方探测容易探查不到整个散列表空间,但是如果散列表长度TableSize是某个4k+3(k是正整数)形式的素数时,平方探测法就可以探查到整个散列表空间
在开放地址散列表中,当删除散列表中元素时,要将元素标记为deleted,不然在查找时遇到这个空闲位置,会判定为散列表中不存在这个数据(遇到空闲位置不再找了)。在开放地址散列表中,删除操作只能是懒惰删除,即需要增加一个删除标记,而不是真正的删除它,以便查找时不会断链,其空间可以在下次插入时重用
64、子矩阵,二维数组的前缀
#include <stdio.h>
int arr[101][101];
int sum[101][101];
int main()
{
int i,j;
//填写数据
arr[1][1]=1;
for(i=1,j=2; j<=100; ++j) //第一行 比左边大2
arr[i][j] = arr[i][j-1] + 2;
for(i=2;i<=100;i++) //第二行开始 比上面大1
{
for(j=1;j<=100;j++)
{
arr[i][j] = arr[i-1][j] + 1;
}
}
//计算sum数组 ,二维数组的前缀
for( i=1; i<=100; ++i){ //行
for( j=1; j<=100; ++j){//列
sum[i][j] = arr[i][j] + sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];
}
}
int x1,y1,x2,y2; //左上坐标,右下坐标,构成的子矩阵
for(x1=1; x1<=100; ++x1)
{
for( y1=1; y1<=100; ++y1)
{
for(x2=x1+1; x2<=100; ++x2){
for(y2 = y1+1; y2<=100; ++y2){
int ret = sum[x2][y2]-sum[x1-1][y2]-sum[x2][y1-1]+sum[x1-1][y1-1];
if(ret>2022)
break;
if(ret==2022){
printf("%d,%d,%d,%d\n",x1,y1,x2,y2);
goto end;
}
}
}
}
}
end:
for(i=x1; i<=x2; ++i){
for(j=y1; j<=y2;++j){
printf("%d,",arr[i][j]);
}
printf("\n");
}
printf( "%d\n", (x2-x1+1 ) * (y2-y1+1 ) );
return 0;
}