日记4----数据结构专用

Posted on 2020-05-18 12:20  金色的省略号  阅读(1012)  评论(0编辑  收藏  举报

  数据结构专用

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 次;对于无向图的邻接矩阵,第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;
View Code

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;
}
View Code

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;
}
View Code

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;
}
View Code