数据结构题集代码分享(一更)

目录

  • 第一部分——简单复杂度问题
    • 01-复杂度1 最大子列和问题
    • 01-复杂度2 Maximum Subsequence Sum——升级版子列和
    • 01-复杂度3 二分查找
  • 第二部分——线性结构
    • 02-线性结构1 两个有序链表序列的合并
    • 02-线性结构2 一元多项式的乘法与加法运算
    • 02-线性结构3 Reversing Linked List
    • 02-线性结构4 Pop Sequence
  • 第三部分——树
    • 03-树1 树的同构
    • 03-树2 List Leaves
    • 03-树3 Tree Traversals Again
    • 04-树4 是否同一棵二叉搜索树
    • 未完待续。。。

题目来自浙江大学的陈越教授和DS课程组。
下面好多题,把刚接触数据结构的我做自闭了,珍爱生命,入坑请慎重,当然打acm的大佬就应该没必要看这个了,这里的题都是常规的数据结构题,没有收录acm那种极端的算法题。
收藏者: Zero Sharp

第一部分——简单复杂度问题

01-复杂度1 最大子列和问题

给定K个整数组成的序列{ N1, N2, …, NK },“连续子列”被定义为{ Ni, Ni+1, …, Nj },其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。现要求你编写程序,计算给定整数序列的最大子列和。

输入格式:

输入第1行给出正整数K (≤100000);第2行给出K个整数,其间以空格分隔。

输出格式:

在一行中输出最大子列和。如果序列中所有整数皆为负数,则输出0。

输入样例:

6
-2 11 -4 13 -5 -2

输出样例:

20

参考代码:

#include 
#define N 100000
int main()
{
    int a[N], n, i, thisSum, maxSum;
    scanf( "%d", &n );
    for( i = 0; i < n; ++i )
        scanf( "%d", a + i );
    thisSum = maxSum = 0;
    for( i = 0; i < n; ++i )
    {
        thisSum += a[i];
        if( thisSum > maxSum )
            maxSum = thisSum;
        if( thisSum < 0 )
            thisSum = 0;
    }
    printf("%d\n", maxSum);
    return 0;
}

01-复杂度2 Maximum Subsequence Sum——升级版子列和

Given a sequence of K integers { N1, N2, …, NK }. A continuous subsequence is defined to be { Ni, Ni+1, …, Nj } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For example, given sequence { -2, 11, -4, 13, -5, -2 }, its maximum subsequence is { 11, -4, 13 } with the largest sum being 20.

Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence.

Input Specification:

Each input file contains one test case. Each case occupies two lines. The first line contains a positive integer K (≤10000). The second line contains K numbers, separated by a space.

Output Specification:

For each test case, output in one line the largest sum, together with the first and the last numbers of the maximum subsequence. The numbers must be separated by one space, but there must be no extra space at the end of a line. In case that the maximum subsequence is not unique, output the one with the smallest indices i and j (as shown by the sample case). If all the K numbers are negative, then its maximum sum is defined to be 0, and you are supposed to output the first and the last numbers of the whole sequence.

Sample Input:

10
-10 1 2 3 4 -5 -23 3 7 -21

Sample Output:

10 1 4

参考代码:

#include 
#define N 100000
int main()
{
    int a[N], n, i, left, right, tempLeft, thisSum, maxSum;
    scanf( "%d", &n );
    for( i = 0; i < n; ++i )
        scanf( "%d", a + i );
    thisSum = 0;
    maxSum = -1;
    tempLeft = left = 0;
    right = n - 1;
    for( i = 0; i < n; ++i )
    {
        thisSum += a[i];
        if( thisSum > maxSum )
        {
            maxSum = thisSum;
            right = i;
            left = tempLeft;
        }

        if( thisSum < 0 )
        {
            thisSum = 0;
            tempLeft = i + 1;
        }
    }
    if( maxSum < 0 )
    {
        maxSum = 0;
        left = 0;
        right = n - 1;
    }

    printf( "%d %d %d\n", maxSum, a[left], a[right] );
    return 0;
}

01-复杂度3 二分查找

参考代码:

Position BinarySearch( List L, ElementType X )
{
    Position front, rear, mid;
    front = 1;
    rear = L->Last;

    while( front <= rear )
    {
        mid = ( front + rear ) / 2;
        if( L->Data[mid] > X )
            rear = mid - 1;
        else if( L->Data[mid] < X )
            front = mid + 1;
        else
            return mid;
    }
    return NotFound;
}

目录

  • 第一部分——简单复杂度问题
    • 01-复杂度1 最大子列和问题
    • 01-复杂度2 Maximum Subsequence Sum——升级版子列和
    • 01-复杂度3 二分查找
  • 第二部分——线性结构
    • 02-线性结构1 两个有序链表序列的合并
    • 02-线性结构2 一元多项式的乘法与加法运算
    • 02-线性结构3 Reversing Linked List
    • 02-线性结构4 Pop Sequence
  • 第三部分——树
    • 03-树1 树的同构
    • 03-树2 List Leaves
    • 03-树3 Tree Traversals Again
    • 04-树4 是否同一棵二叉搜索树
    • 未完待续。。。

第二部分——线性结构

02-线性结构1 两个有序链表序列的合并

函数接口定义:

List Merge( List L1, List L2 );

其中List结构定义如下:

typedef struct Node *PtrToNode;
struct Node {
    ElementType Data; /* 存储结点数据 */
    PtrToNode   Next; /* 指向下一个结点的指针 */
};
typedef PtrToNode List; /* 定义单链表类型 */

L1L2是给定的带头结点的单链表,其结点存储的数据是递增有序的;函数Merge要将L1L2合并为一个非递减的整数序列。应直接使用原序列中的结点,返回归并后的带头结点的链表头指针。

数据类型定义:

typedef int ElementType;
typedef struct Node *PtrToNode;

输入样例:

3
1 3 5
5
2 4 6 8 10

输出样例:

1 2 3 4 5 6 8 10 
NULL
NULL

参考代码:

#include 
#include 

typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType Data;
    PtrToNode   Next;
};
typedef PtrToNode List;

List Read(); 
void Print( List L ); 
List Merge( List L1, List L2 );

int main()
{
    List L1, L2, L;
    L1 = Read();
    L2 = Read();
    L = Merge(L1, L2);
    Print(L);
    Print(L1);
    Print(L2);
    return 0;
}

List Read()
{
    int n, i;
    scanf( "%d",&n );
    List L = ( List ) malloc( sizeof( PtrToNode ) );   
    L->Next = NULL;        
    if( n )                  //当n不是0时
    {
        List tmp = L;     //r是一个中间变量的节点
        for( i = 0; i < n; ++i ) 
        {
            List p = ( List ) malloc( sizeof( struct Node ) );
            scanf( "%d", &( p->Data ) );    
            tmp->Next = p;
            tmp = p;
        }
        tmp->Next = NULL;         
    }
    return L;
}


void Print( List L )
{
    List p = L->Next;
    if( p )
    {
        List tmp;
        tmp = L;
        while( tmp->Next )
        {
            tmp = tmp->Next;
            printf( "%d ", tmp->Data );
        }
    }
    else
      	printf( "NULL" );
    putchar( '\n' );
}

List Merge( List L1, List L2 )
{
    List p1, p2, cur, L;
    L = ( List ) malloc( sizeof( struct Node ) );
    p1 = L1->Next;
    p2 = L2->Next;
    cur = L;
    while( p1 && p2 )
    {
        if( p1->Data <= p2->Data )
        {
            cur->Next = p1;
            cur = p1;
            p1 = p1->Next;
        }
        else
        {
            cur->Next = p2;
            cur = p2;
            p2 = p2->Next;
        }
    }

    cur->Next = p1 ?  p1 : p2;
    L1->Next = NULL;
    L2->Next = NULL;
    return L;
}

02-线性结构2 一元多项式的乘法与加法运算

设计函数分别求两个一元多项式的乘积与和。

输入格式:

输入分2行,每行分别先给出多项式非零项的个数,再以指数递降方式输入一个多项式非零项系数和指数(绝对值均为不超过1000的整数)。数字间以空格分隔。

输出格式:

输出分2行,分别以指数递降方式输出乘积多项式以及和多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。零多项式应输出0 0

输入样例:

4 3 4 -5 2  6 1  -2 0
3 5 20  -7 4  3 1

输出样例:

15 24 -25 22 30 21 -10 20 -21 8 35 6 -33 5 14 4 -15 3 18 2 -6 1
5 20 -4 4 -5 2 9 1 -2 0

参考代码:

#include 
#include 
struct PolyNode
{
    int coefficient;  //系数
    int exponent;     //指数
    struct PolyNode * next;
};
typedef struct PolyNode * Polynomial;

//在节点 p 后面插入一个节点
void Attach( Polynomial rear, const int coefficient, const int exponent )
{
    Polynomial temp;
    temp = (Polynomial) malloc( sizeof( struct PolyNode ) );
    temp->coefficient = coefficient;
    temp->exponent = exponent;
    temp->next = rear->next;
    rear->next = temp;
}

Polynomial InputPoly()
{
    Polynomial head, current, p;
    int n, coefficient, exponent;

    head = (Polynomial) malloc( sizeof( struct PolyNode ) );
    head->next = NULL;
    current = head;

    scanf( "%d", &n );
    while( n-- )
    {
        p = (Polynomial) malloc( sizeof( struct PolyNode ) );
        scanf( "%d %d", &coefficient, &exponent);
        p->coefficient = coefficient;
        p->exponent = exponent;
        current->next = p;
        current = p;
    }
    current->next = NULL;

    //头节点没有输入,直接free掉
    p = head;
    head = head->next;
    free( p );

    return head;
}

void OutputPoly( Polynomial p )
{
    if( p != NULL )
    {
        while( p->next != NULL )
        {
            printf( "%d %d ", p->coefficient, p->exponent );
            p = p->next;
        }
        printf( "%d %d\n", p->coefficient, p->exponent );
    }
    else
    {
        printf( "%d %d\n", 0, 0 );
    }
}

void DeletePoly( Polynomial p )
{
    Polynomial temp = NULL;
    while( p != NULL )
    {
        temp = p;
        p = p->next;
        free( temp );
    }
}

Polynomial AddPoly( const Polynomial poly1, const Polynomial poly2)
{
    Polynomial sumPolyHead, rear, p1, p2, temp;  //p1 p2为当前指针
    int sumCoef = 0;
    if( poly1 == NULL && poly2 == NULL )
        return NULL;

    p1 = poly1;
    p2 = poly2;
    sumPolyHead = (Polynomial) malloc( sizeof( struct PolyNode ) );
    sumPolyHead->next = NULL;
    rear = sumPolyHead;

    while( p1 != NULL && p2 != NULL )
    {
        if( p1->exponent > p2->exponent )
        {
            Attach( rear, p1->coefficient, p1->exponent );
            rear = rear->next;
            p1 = p1->next;
        }
        else if( p1->exponent < p2->exponent )
        {
            Attach( rear, p2->coefficient, p2->exponent );
            rear = rear->next;
            p2 = p2->next;
        }
        else
        {
            sumCoef = p1->coefficient + p2->coefficient;
            if( sumCoef != 0 )
            {
                Attach( rear, sumCoef, p1->exponent );
                rear = rear->next;
            }
            p1 = p1->next;
            p2 = p2->next;
        }
    }

    //接下来处理p1或者p2多出来的项
    while( p1 != NULL )
    {
        Attach( rear, p1->coefficient, p1->exponent );
        p1 = p1->next;
    }
    while( p2 != NULL )
    {
        Attach( rear, p2->coefficient, p2->exponent );
        p2 = p2->next;
    }

    //同样,头节点没有写东西,直接free掉
    temp = sumPolyHead;
    sumPolyHead = sumPolyHead->next;
    free(temp);
    return sumPolyHead;
}

Polynomial MultiplePoly( const Polynomial poly1, const Polynomial poly2 )
{
    Polynomial mutiPolyHead, rear, p1, p2, temp;
    int coef, exp;

    if( poly1 == NULL || poly2 == NULL )
        return NULL;
    p1 = poly1;
    p2 = poly2;
    mutiPolyHead = (Polynomial) malloc( sizeof( struct PolyNode ) );
    mutiPolyHead->next = NULL;
    rear = mutiPolyHead;

    while( p1 != NULL )
    {
        while( p2 != NULL )
        {
            coef = p1->coefficient * p2->coefficient;
            exp = p1->exponent + p2->exponent;
            while( rear->next != NULL && rear->next->exponent > exp )
                rear = rear->next;
            if( rear->next != NULL && rear->next->exponent == exp )  //如果该次幂的项存在则修改
            {
                if( rear->next->coefficient + coef != 0 )
                {
                    rear->next->coefficient += coef;
                }
                else       //如果系数为0就删除这个节点
                {
                    temp = rear->next;
                    rear->next = rear->next->next;
                    free(temp);
                }
            }
            else        //否则插入节点,或者rear到多项式末尾直接追加一个节点
                Attach( rear, coef, exp );
            p2 = p2->next;
        }
        p1 = p1->next;
        p2 = poly2;             //乘完一遍,p2归位
        rear = mutiPolyHead;    //扫描指针归位
    }

    //同样这里头节点没有写入数据,直接free掉
    temp = mutiPolyHead;
    mutiPolyHead = mutiPolyHead->next;
    free(temp);
    return mutiPolyHead;
}

int main()
{
    Polynomial p1, p2, sum, product;
    p1 = InputPoly();
    p2 = InputPoly();

    product = MultiplePoly( p1, p2 );
    sum = AddPoly( p1, p2 );

    OutputPoly( product );
    OutputPoly( sum );

    DeletePoly( p1 );
    DeletePoly( p2 );
    DeletePoly( product );
    DeletePoly( sum );
    return 0;
}

02-线性结构3 Reversing Linked List

Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K=3, then you must output 3→2→1→6→5→4; if K=4, you must output 4→3→2→1→5→6.

Input Specification:

Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (≤105) which is the total number of nodes, and a positive K (≤N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.

Then N lines follow, each describes a node in the format:

Address Data Next

where Address is the position of the node, Data is an integer, and Next is the position of the next node.

Output Specification:

For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.

Sample Input:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

Sample Output:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

参考代码:

#include 
#define MAXSIZE 100000
typedef struct
{
    int data;
    int nextAddr;
} Node;
Node list[MAXSIZE];

void InitList( int n )
{
    int addr, data, nextAddr, i;
    for( i = 0; i < n; ++i )
    {
        scanf( "%d %d %d", &addr, &data, &nextAddr );
        list[addr].data = data;
        list[addr].nextAddr = nextAddr;
    }
}

int Reverse( const int head, const int n, const int k )
{
    int i, remN, temp_addr, sub_head, curr, new_head, last_tail;
    remN = n;
    curr = sub_head = new_head = head;
    while( remN >= k )
    {
        //反转子链表
        for( i = 1; i <= k - 1; ++i )   //长度为k的串反转需要k-1次
        {
            temp_addr = list[curr].nextAddr;
            list[curr].nextAddr = list[temp_addr].nextAddr;
            list[temp_addr].nextAddr = sub_head;
            sub_head = temp_addr;
        }

        if( remN == n )
        {
            new_head = sub_head;  //第一段子列反转后的头节点就是整个表的头节点
        }
        else
        {
            list[last_tail].nextAddr = sub_head;  //上次的尾部节点指向这次的子串头节点
        }

        last_tail = curr;

        sub_head = list[curr].nextAddr;
        curr = sub_head;
        remN -= k;
    }
    return new_head;
}

void Print( int headAddr )
{
    int curr = headAddr;
    while( list[curr].nextAddr != -1 )
    {
        printf( "%05d %d %05d\n", curr, list[curr].data, list[curr].nextAddr );
        curr = list[curr].nextAddr;
    }
    printf( "%05d %d %d", curr, list[curr].data, list[curr].nextAddr );
}

int main()
{
    int n, k, headAddr;
    int realN, temp_addr;
    scanf( "%d %d %d", &headAddr, &n, &k );
    InitList( n );

    //下面计算除了独立节点之外的真正节点数
    realN = 0;
    temp_addr = headAddr;
    while( temp_addr != -1 )
    {
        ++realN;
        temp_addr = list[temp_addr].nextAddr;
    }

    if( realN != 1 )
        headAddr = Reverse( headAddr, realN, k );
    Print( headAddr );
    return 0;
}

02-线性结构4 Pop Sequence

Given a stack which can keep M numbers at most. Push N numbers in the order of 1, 2, 3, …, N and pop randomly. You are supposed to tell if a given sequence of numbers is a possible pop sequence of the stack. For example, if M is 5 and N is 7, we can obtain 1, 2, 3, 4, 5, 6, 7 from the stack, but not 3, 2, 1, 7, 5, 6, 4.

Input Specification:

Each input file contains one test case. For each case, the first line contains 3 numbers (all no more than 1000): M (the maximum capacity of the stack), N (the length of push sequence), and K (the number of pop sequences to be checked). Then K lines follow, each contains a pop sequence of N numbers. All the numbers in a line are separated by a space.

Output Specification:

For each pop sequence, print in one line “YES” if it is indeed a possible pop sequence of the stack, or “NO” if not.

Sample Input:

5 7 5
1 2 3 4 5 6 7
3 2 1 7 5 6 4
7 6 5 4 3 2 1
5 6 4 3 7 2 1
1 7 6 5 4 3 2

Sample Output:

YES
NO
NO
YES
NO

参考代码:

#include 
#include 
#define MAXSIZE 1000

struct SNode
{
    int data;
    struct SNode * next;
};
typedef struct SNode Stack;

Stack * CreateStack();
int IsEmpty( Stack * stack );
int StackSize( Stack * stack );
void PushStack( Stack * stack, int data );
void PopStack( Stack * stack );
int TopElement( Stack * stack );
void DeleteStack( Stack * stack );
void ClearStack( Stack * stack );

int main()
{
    int M, N, K, i, j, t;
    int a[MAXSIZE] = {0}, result[MAXSIZE] = {0};
    Stack * stack = CreateStack();
    scanf( "%d %d %d", &M, &N, &K );
    for( i = 0; i < K; ++i )
    {
        for( j = 0; j < N; ++j )
            scanf( "%d", &a[j] );

        j = t = 0;
        PushStack( stack, 0 );  //把第栈顶元素设为1
        while( j < N )
        {
            while( a[j] > TopElement( stack ) && StackSize( stack ) <= M )
            {
                PushStack( stack, ++t );
            }

            if( a[j++] == TopElement( stack ) )
                PopStack( stack );
            else
            {
                result[i] = 1;
                break;
            }
        }

        ClearStack( stack );
    }

    for( i = 0; i < K; ++i )
    {
        if( 1 == result[i] )
            printf( "NO\n" );
        else
            printf( "YES\n" );
    }

    DeleteStack( stack );
    stack = NULL;
    return 0;
}

Stack * CreateStack()   //创建栈
{
    Stack * stack = ( Stack * ) malloc( sizeof( Stack ) );
    if( NULL != stack )
    {
        stack->data = 0;
        stack->next = NULL;
        return stack;
    }
    printf( "Memory is not enough!\n" );
    return NULL;
}

int IsEmpty( Stack * stack )
{
    return NULL == stack->next;
}

int StackSize( Stack * stack )
{
    return stack->data;
}

void PushStack( Stack * stack, int data )
{
    Stack * newNode = ( Stack * ) malloc( sizeof( Stack ) );
    if( NULL == newNode )
    {
        printf( "Memory is not enough!\n" );
        exit(0);
    }
    newNode->data = data;
    newNode->next = stack->next;
    stack->next = newNode;
    ++stack->data;
}

//弹出栈顶元素
void PopStack( Stack * stack )
{
    Stack * tempst;
    if( !IsEmpty( stack ) )
    {
        tempst = stack->next;
        stack->next = tempst->next;
        free( tempst );
        --stack->data;
    }
}

int TopElement( Stack * stack )
{
    if( !IsEmpty( stack ) )
        return stack->next->data;

    printf( "Stack is empty\n" );
    return -1;
}

//删除整个栈
void DeleteStack( Stack * stack )
{
    Stack * tempst;
    while( stack != NULL )
    {
        tempst = stack;
        stack = tempst->next;
        free( tempst );
    }
}

//只是清除栈中的数据
void ClearStack( Stack * stack )
{
    Stack * tempst, * cur;
    if( NULL == stack )
        return;

    cur = stack->next;
    while( cur != NULL )
    {
        tempst = cur;
        cur = tempst->next;
        free( tempst );
    }
    stack->data = 0;
    stack->next = NULL;
}

第三部分——树

03-树1 树的同构

给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。

图1
数据结构题集代码分享(一更)_第1张图片
图2
数据结构题集代码分享(一更)_第2张图片
现给定两棵树,请你判断它们是否是同构的。

输入格式:

输入给出2棵二叉树树的信息。对于每棵树,首先在一行中给出一个非负整数N (≤10),即该树的结点数(此时假设结点从0到N−1编号);随后N行,第i行对应编号第i个结点,给出该结点中存储的1个英文大写字母、其左孩子结点的编号、右孩子结点的编号。如果孩子结点为空,则在相应位置上给出“-”。给出的数据间用一个空格分隔。注意:题目保证每个结点中存储的字母是不同的。

输出格式:

如果两棵树是同构的,输出“Yes”,否则输出“No”。

输入样例1(对应图1):

8
A 1 2
B 3 4
C 5 -
D - -
E 6 -
G 7 -
F - -
H - -
8
G - 4
B 7 6
F - -
A 5 1
H - -
C 0 -
D - -
E 2 -

输出样例1:

Yes

输入样例2(对应图2):

8
B 5 7
F - -
A 0 3
C 6 -
H - -
D - -
G 4 -
E 1 -
8
D 6 -
B 5 -
E - -
H - -
C 0 2
G - 3
F - -
A 1 4

输出样例2:

No

参考代码:

#include 
#define MAX_NODE_NUM 10
typedef struct TreeNode
{
    char data;
    int left;
    int right;
} TreeNode;

int BuildTree(const int n, TreeNode tree[] );
int IsIsomorphism( TreeNode tree1[], int root1, TreeNode tree2[], int root2 );

int main()
{
    int root1, root2, nodeNum1, nodeNum2;
    TreeNode tree1[MAX_NODE_NUM], tree2[MAX_NODE_NUM] ;
    scanf( "%d", &nodeNum1 );
    root1 = BuildTree( nodeNum1, tree1 );
    scanf( "%d", &nodeNum2 );
    root2 = BuildTree( nodeNum2, tree2 );

    if( nodeNum1 == nodeNum2 && IsIsomorphism( tree1, root1, tree2, root2 ) )
        printf( "Yes\n" );
    else
        printf( "No\n" );

    return 0;
}

int BuildTree(const int nodeNum, TreeNode tree[] )
{
    int check[MAX_NODE_NUM] = {0}, i;
    char cleft, cright;
    if( 0 == nodeNum )
        return -1;

    for( i = 0; i < nodeNum; ++i )
        tree[i].data = 0;         //把数据都置为0

    for( i = 0; i < nodeNum; ++i )
    {
        scanf( " %c %c %c", &tree[i].data, &cleft, &cright );
        if( cleft != '-' )
        {
            tree[i].left = cleft - '0';
            check[ tree[i].left ] = 1;
        }
        else
            tree[i].left = -1;

        if( cright != '-' )
        {
            tree[i].right = cright - '0';
            check[ tree[i].right ] = 1;
        }
        else
            tree[i].right = -1;
    }

    for( i = 0; i < nodeNum; ++i )
    {
        if( 0 == check[i] )
            return i;
    }
    return -1;
}

int IsIsomorphism( TreeNode tree1[], int root1, TreeNode tree2[], int root2 )
{
    if( -1 == root1 && -1 == root2 )        //空树同构
        return 1;
    else if( -1 == root1 || -1 == root2 )   //只有一棵为空树则不同构
        return 0;

    if( tree1[root1].data != tree2[root2].data )      //根节点不同则不同构
        return 0;

    //左儿子都是空的,则递归判定右子树是否同构
    if( -1 == tree1[root1].left && -1 == tree2[root2].left )
        return IsIsomorphism( tree1, tree1[root1].right, tree2, tree2[root2].right );

    //左儿子都不空且值相同,则分别递归判定左子树和右子树判定是否都同构
    if( ( tree1[root1].left != -1 ) && ( tree2[root2].left != -1 ) 
       		&& ( tree1[tree1[root1].left].data == tree2[tree2[root2].left].data ) )
        return IsIsomorphism( tree1, tree1[root1].left, tree2, tree2[root2].left )
        		&& IsIsomorphism( tree1, tree1[root1].right, tree2, tree2[root2].right );
    //否则左右交叉递归判定是否同构
    else
        return IsIsomorphism( tree1, tree1[root1].left, tree2, tree2[root2].right ) 
        		&& IsIsomorphism( tree1, tree1[root1].right, tree2, tree2[root2].left );

}

03-树2 List Leaves

Given a tree, you are supposed to list all the leaves in the order of top down, and left to right.

Input Specification:

Each input file contains one test case. For each case, the first line gives a positive integer N (≤10) which is the total number of nodes in the tree – and hence the nodes are numbered from 0 to N−1. Then N lines follow, each corresponds to a node, and gives the indices of the left and right children of the node. If the child does not exist, a “-” will be put at the position. Any pair of children are separated by a space.

Output Specification:

For each test case, print in one line all the leaves’ indices in the order of top down, and left to right. There must be exactly one space between any adjacent numbers, and no extra space at the end of the line.

Sample Input:

8
1 -
- -
0 -
2 7
- -
- -
5 -
4 6

Sample Output:

4 1 5

参考代码:

#include 
#include 
#define N 10
typedef struct
{
    int addr;
    int leftAddr;
    int rightAddr;
} Tree;
Tree tree[N];

typedef struct Queue
{
    Tree node[N];
    int front;
    int rear;
} Queue;

void InitQueue( Queue * queue )
{
    queue->front = queue->rear = 0;
}

int IsEmptyQueue( Queue queue )
{
    if( queue.rear == queue.front )
        return 1;
    return 0;
}

int IsFullQueue( Queue queue )
{
    if( (queue.rear + 1) % N == queue.front )
        return 1;
    return 0;
}

int Inqueue( Queue * queue, Tree node )
{
    if( IsFullQueue( *queue ) )
        return 0;
    queue->node[queue->rear] = node;
    queue->rear = ( queue->rear + 1 ) % N;
    return 1;
}

Tree Dequeue(Queue * queue)
{
    Tree tree = queue->node[queue->front];
    queue->front = ( queue->front + 1 ) % N;
    return tree;
}

int BuildTree( Tree tree[], const int n )
{
    int i, findRoot[N] = {0};
    char cl, cr;
    for( i = 0; i < n; ++i )
    {
        tree[i].addr = i;
        scanf( " %c %c", &cl, &cr );
        if( cl != '-' )
        {
            tree[i].leftAddr = cl - '0';
            findRoot[tree[i].leftAddr] = 1;
        }
        else
            tree[i].leftAddr = -1;

        if( cr != '-' )
        {
            tree[i].rightAddr = cr - '0';
            findRoot[tree[i].rightAddr] = 1;
        }
        else
            tree[i].rightAddr = -1;
    }

    for( i = 0; i < n; ++i )
    {
        if( 0 == findRoot[i] )
            return i;
    }
    return -1;
}

void ListLeaves( Tree tree[], const int n, int rootAddr )
{
    int num = 0;
    Tree head;
    Queue queue;
    if( -1 == rootAddr )
        return;

    InitQueue( &queue );
    Inqueue( &queue, tree[rootAddr] );

    while( !IsEmptyQueue(queue) )
    {
        ++num;
        head = Dequeue( &queue );

        if( head.leftAddr != -1 && head.rightAddr != -1 )
        {
            Inqueue( &queue, tree[head.leftAddr] );
            Inqueue( &queue, tree[head.rightAddr] );
        }
        else if( head.leftAddr != -1 && head.rightAddr == -1 )
            Inqueue( &queue, tree[head.leftAddr] );
        else if( head.leftAddr == -1 && head.rightAddr != -1 )
            Inqueue( &queue, tree[head.rightAddr] );
        else
        {
            if( num != n )
                printf( "%d ", head.addr );
            else
                printf( "%d", head.addr );
        }
    }
}

int main()
{
    int n, rootAddr;

    scanf( "%d", &n );
    rootAddr = BuildTree( tree, n );

    ListLeaves( tree, n, rootAddr );
    return 0;
}

03-树3 Tree Traversals Again

An inorder binary tree traversal can be implemented in a non-recursive way with a stack. For example, suppose that when a 6-node binary tree (with the keys numbered from 1 to 6) is traversed, the stack operations are: push(1); push(2); push(3); pop(); pop(); push(4); pop(); pop(); push(5); push(6); pop(); pop(). Then a unique binary tree (shown in Figure 1) can be generated from this sequence of operations. Your task is to give the postorder traversal sequence of this tree.

数据结构题集代码分享(一更)_第3张图片
Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (≤30) which is the total number of nodes in a tree (and hence the nodes are numbered from 1 to N). Then 2N lines follow, each describes a stack operation in the format: “Push X” where X is the index of the node being pushed onto the stack; or “Pop” meaning to pop one node from the stack.

Output Specification:

For each test case, print the postorder traversal sequence of the corresponding tree in one line. A solution is guaranteed to exist. All the numbers must be separated by exactly one space, and there must be no extra space at the end of the line.

Sample Input:

6
Push 1
Push 2
Push 3
Pop
Pop
Push 4
Pop
Pop
Push 5
Push 6
Pop
Pop

Sample Output:

3 4 2 6 5 1

参考代码:

#include 
#include 
#include 
#define N 31
#define ERROR -1
typedef int ElementType;
typedef struct SNode * Stack;
typedef struct TreeNode * Tree;
struct TreeNode 
{
    int left;
    int right;
}tree[N];

struct SNode
{
    ElementType * data;
    int top;
    int maxSize;
};

int CreateTreeFromInorder( Stack stack, int n );
void PostOrder( Tree tree, int root );
Stack CreateStack( int maxSize );
void Push( Stack stack, ElementType X );
ElementType Pop( Stack stack );

int main()
{
    int n, root;
    Stack stack;
    memset( tree, -1, sizeof( tree ) );
    scanf( "%d", &n );
    stack = CreateStack( n );
    root = CreateTreeFromInorder( stack, n );
    PostOrder( tree, root );
    return 0;
}

int CreateTreeFromInorder( Stack stack, int n )
{
    int x, i, root, cur;
    char str[5];
    cur = root = -1;
    for( i = 0; i < 2 * n; ++i )
    {
        scanf( "%s", str );
        if( !strcmp( str, "Push" ) )
        {
            scanf( "%d", &x );
            if( root == -1 )
                cur = root = x;
            else if( tree[cur].left == -1 )
                tree[cur].left = x;
            else
                tree[cur].right = x;
            cur = x;
            Push( stack, x );
        }
        else
            cur = Pop( stack );
    }
    return root;
}

void PostOrder( Tree tree, int root )
{
    static int flag = 1;
    if( root != -1 )
    {
        PostOrder( tree, tree[root].left );
        PostOrder( tree, tree[root].right );
        if( flag )
        {
            flag = 0;
            printf( "%d", root );
        }
        else
            printf( " %d", root );
    }
}

Stack CreateStack( int maxSize )
{
    Stack stack = ( Stack ) malloc( sizeof( struct SNode ) );
    stack->data = ( ElementType * ) malloc( maxSize * sizeof( ElementType ) );
    stack->maxSize = maxSize;
    stack->top = -1;
    return stack;
}

void Push( Stack stack, ElementType X )
{
    if( stack->top == stack->maxSize - 1 )
        printf( "The stack is full\n" );
    else
        stack->data[++stack->top] = X;
}

ElementType Pop( Stack stack )
{
    if( stack->top != -1 )
    {
        return stack->data[stack->top--];
    }
    else
    {
        printf( "The stack is empty" );
        return ERROR;
    }
}

04-树4 是否同一棵二叉搜索树

给定一个插入序列就可以唯一确定一棵二叉搜索树。然而,一棵给定的二叉搜索树却可以由多种不同的插入序列得到。例如分别按照序列{2, 1, 3}和{2, 3, 1}插入初始为空的二叉搜索树,都得到一样的结果。于是对于输入的各种插入序列,你需要判断它们是否能生成一样的二叉搜索树。

输入格式:

输入包含若干组测试数据。每组数据的第1行给出两个正整数N (≤10)和L,分别是每个序列插入元素的个数和需要检查的序列个数。第2行给出N个以空格分隔的正整数,作为初始插入序列。最后L行,每行给出N个插入的元素,属于L个需要检查的序列。

简单起见,我们保证每个插入序列都是1到N的一个排列。当读到N为0时,标志输入结束,这组数据不要处理。

输出格式:

对每一组需要检查的序列,如果其生成的二叉搜索树跟对应的初始序列生成的一样,输出“Yes”,否则输出“No”。

输入样例:

4 2
3 1 4 2
3 4 1 2
3 2 4 1
2 1
2 1
1 2
0

输出样例:

Yes
No
No

参考代码:

未完待续。。。

你可能感兴趣的:(数据结构,算法,C语言)