考研数据结构常考的代码题总结 C语言实现

PAT
leetcode
代码github备份

考研数据结构常考的代码题总结 C语言实现_第1张图片

考研数据结构常考的代码题总结 C语言实现_第2张图片

数据结构习题集

  • leetcode 21. 合并两个有序链表
  • PAT 6-1 单链表逆转 (20 分)
  • leetcode 141. 环形链表
  • PAT 6-2 顺序表操作集 (20 分)
  • PAT 6-3 求链式表长(10 分)
  • PAT 6-4 链式表的按序号查找 (10 分)
  • leetcode 203. 移除链表元素
  • leetcode 83. 删除排序链表中的重复元素
  • PAT 6-5 链式表操作集 (20 分)
  • PAT 6-6 带头结点的链式表操作集 (20 分)
  • PAT 6-7 在一个数组中实现两个堆栈 (20 分)
  • PAT 6-8 求二叉树高度 (20 分) 递归与非递归方法
  • PAT 6-10 二分查找 (20 分)(递归和迭代版本)
  • PAT 6-9 二叉树的遍历 (25 分) 迭代和递归版本
  • PAT 6-11 先序输出叶结点 (15 分)
  • PAT 6-12 二叉搜索树的操作集 (30 分) 递归与非递归版本
  • 求二叉树中度为0、1、2结点的个数
  • ---------------以下只给出伪代码--------------------
  • 二叉树自下而上,从右到左的层次遍历
  • 判断二叉树是否为完全二叉树
  • 将二叉树所有结点的左右子树交换
  • 删除二叉树中所有值为X的节点,以及它的左右子树
  • 在二叉树中查找值为X的结点,并输出其所有的祖先结点
  • 求一个二叉树的宽度
  • 求以孩子兄弟表示法存储的树的叶子节点数
  • 求以孩子兄弟表示法存储的树的深度
  • 希尔排序
  • 快速排序
  • 冒泡排序
  • 归并排序
  • 简单选择排序
  • 由二分查找优化的直接插入排序
  • 带头结点链表,将小于第一个元素的结点放在其前面,大于放在后面
  • 判断一颗树是否对称
  • -------------------一些零碎的知识点-----------------------
  • 二叉树在线索化后,仍不能有效求解的问题
  • 存储结构的相关问题

leetcode 21. 合并两个有序链表

考研数据结构常考的代码题总结 C语言实现_第3张图片

/* 
Created by salmon on 2021-9-14 21:27.
*/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* mergeTwoLists(struct ListNode* l1, struct ListNode* l2){
    struct ListNode head;
    struct ListNode* res = &head;
    while (l1 != NULL && l2 != NULL) { //l2小于等于l1时插入l2,否则插入l1; 每次插入后指针后移一位;
        if(l2 -> val <= l1 -> val){
            res -> next = l2;
            l2 = l2 -> next;
        } else {
            res -> next = l1;
            l1 = l1 -> next;
        }
        res = res -> next;
    }
    //此时循环结束,必定至少有一个链表被循环到最后一个节点之后的空指针上
    if(l1 == NULL){
        res -> next = l2;
    } else if (l2 == NULL){
        res -> next = l1;
    }


    //返回头指针
    //不能返回head->next,因为head不是指针是一个struct类型的变量
    //参考文档:https://blog.csdn.net/faihung/article/details/79190039
    return head.next;
}

PAT 6-1 单链表逆转 (20 分)

考研数据结构常考的代码题总结 C语言实现_第4张图片

/* 
Created by salmon on 2021-9-13 23:09.
 单链表逆转
*/

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


#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 Reverse( List L );

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

/* 你的代码将被嵌在这里 */

List Reverse( List L ){
    if(L==NULL || L->Next==NULL)
        return L;

    //需要三个指针,顺序为L,P1,P2
    //L指向L的头结点,并且为了实现目的将其孤立
    //p1指向L的下一个,p2指向p1的下一个,所以必定是p2先指向NULL
    List p1 = L->Next;
    L->Next = NULL;
    List p2 = p1->Next;
    while (p2) {
        //调转指针next方向
        p1->Next = L;
        //第一个指针后移一位
        L = p1;
        //第二个指针后移一位
        p1 = p2;
        第三个指针后移一位
        p2 = p2->Next;
    }
    //处理到这里时面临一种情况:L在倒数第二个节点,P1在倒数第一个结点,P2在空结点上
    //此时最后的P1结点没有处理,应该讲P1的next也逆转
    p1->Next = L;
    return p1;
}

leetcode 141. 环形链表

考研数据结构常考的代码题总结 C语言实现_第5张图片

/**
*Created by salmon on 2021-9-14 22:25.
**/

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
bool hasCycle(struct ListNode *head) {
    if(head == NULL){ //若为空必定不存在环
        return false;
    }

    struct ListNode* fast = head -> next;
    struct ListNode* slow = head;
    //快慢指针,快的比慢的快一个位置
    //如果快的追上慢的就表明有环
    while (slow != fast) {
        if(fast == NULL || fast -> next == NULL){ 
            //因为fast一次移动两个元素,所以fast至少指向该链表倒数第二个节点
            //否则会发生空指针访问空指针域的问题
            return false;
        }
        fast = fast -> next -> next;
        slow = slow -> next;
    }
    return true;
}

PAT 6-2 顺序表操作集 (20 分)

考研数据结构常考的代码题总结 C语言实现_第6张图片

/**
*Created by salmon on 2021-9-14 23:32.
**/

/**
*Created by salmon on 2021-9-14 22:57.
**/

#include 
#include 

#define MAXSIZE 7
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;
struct LNode {
    ElementType Data[MAXSIZE];
    Position Last; /* 保存线性表中最后一个元素的位置 */
};

List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );

int main()
{
    List L;
    ElementType X;
    Position P;
    int N;

    L = MakeEmpty();
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        if ( Insert(L, X, 0)==false )
            printf(" Insertion Error: %d is not in.\n", X);
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        P = Find(L, X);
        if ( P == ERROR )
            printf("Finding Error: %d is not in.\n", X);
        else
            printf("%d is at position %d.\n", X, P);
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &P);
        if ( Delete(L, P)==false )
            printf(" Deletion Error.\n");
        if ( Insert(L, 0, P)==false )
            printf(" Insertion Error: 0 is not in.\n");
    }
    return 0;
}

/* 你的代码将被嵌在这里 */

List MakeEmpty(){ //创建并返回一个空的线性表
    List list = (List)malloc(sizeof(struct LNode));
    list->Last = -1;
    return list;
}

Position Find( List L, ElementType X ){ //返回线性表中X的位置。若找不到则返回ERROR;
    for (int i = 0; i <= L->Last; ++i) {//TODO 这里可能错
        if(L->Data[i] == X){
            return i;
        }
    }
    return ERROR;
}

bool Insert( List L, ElementType X, Position P ){ // 将X插入在位置P并返回true。若空间已满,则打印“FULL”并返回false;如果参数P指向非法位置,则打印“ILLEGAL POSITION”并返回false;
    if(P < 0 || P > L->Last + 1){ //非法位置,正确:可以插入在[0,当前数组最大值+1]之间
        printf("ILLEGAL POSITION");
        return false;
    }
    if(L->Last == MAXSIZE - 1){ //顺序表已满
        printf("FULL");
        return false;
    }
    for (int i = L->Last + 1; i > P ; --i) { //i一直遍历到要插入下标P+1的位置
        L->Data[i] = L->Data[i - 1];
    }
    //当前P位置空缺出来
    L->Data[P] = X;
    //更新最后一个结点的下标
    L->Last++;
    return true;
}

bool Delete( List L, Position P ){// 将位置P的元素删除并返回true。若参数P指向非法位置,则打印“POSITION P EMPTY”(其中P是参数值)并返回false。
    if(P < 0 || P > L->Last){ //非法位置,正确:可以删除在[0,当前数组最大值]之间的任何数
        printf("POSITION %d EMPTY",P);
        return false;
    }
    for (int i = P; i < L->Last ; ++i) { //i一直遍历到数组倒数第二个元素
        L->Data[i] = L->Data[i + 1];
    }
    L->Data[L->Last] = -1; //去掉最后一个元素
    L->Last--;
    return true;
}


考研数据结构常考的代码题总结 C语言实现_第7张图片

PAT 6-3 求链式表长(10 分)

考研数据结构常考的代码题总结 C语言实现_第8张图片

/**
*Created by salmon on 2021-9-15 22:15.
**/

#include 
#include 

typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode List;

List Read(); /* 细节在此不表 */

int Length( List L );

int main()
{
    List L = Read();
    printf("%d\n", Length(L));
    return 0;
}

/* 你的代码将被嵌在这里 */
int Length( List L ){
    int length = 0;
    while (L) {
        length++;
        L = L->Next;
    }
    return length;
}

考研数据结构常考的代码题总结 C语言实现_第9张图片

PAT 6-4 链式表的按序号查找 (10 分)

考研数据结构常考的代码题总结 C语言实现_第10张图片

/**
*Created by salmon on 2021-9-15 22:21.
**/

#include 
#include 

#define ERROR -1
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode List;

List Read(); /* 细节在此不表 */

ElementType FindKth( List L, int K );

int main()
{
    int N, K;
    ElementType X;
    List L = Read();
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &K);
        X = FindKth(L, K);
        if ( X!= ERROR )
            printf("%d ", X);
        else
            printf("NA ");
    }
    return 0;
}

/* 你的代码将被嵌在这里 */
ElementType FindKth( List L, int K ){ //这里的K不是下标,是序号
    if(K <= 0) return ERROR;
    int index = 0;
    while (L) {
        if (index + 1 == K) {
            return L->Data;
        } else {
            L = L->Next;
            index++;
        }
    }
    return ERROR;
}

考研数据结构常考的代码题总结 C语言实现_第11张图片

leetcode 203. 移除链表元素

考研数据结构常考的代码题总结 C语言实现_第12张图片

struct ListNode* removeElements(struct ListNode* head, int val){
    struct  ListNode* res = malloc(sizeof(struct ListNode));
    res -> next = head;//虚拟一个空的头结点出来
    struct ListNode* p = res;//拷贝res,用p进行遍历,保证无论如何删除使res的下一个就是头结点,如果不拷贝res而是使用head返回,那么如果删除第一个元素就会出现问题
//    while (p) { 这里如果不是下面这样写的话,会出现访问空指针空间的异常
        while (p->next != NULL) {
        if(p -> next -> val == val) {
           p->next = p->next->next;
        } else {
            p = p -> next;
        }
    }
    return res->next;
}

考研数据结构常考的代码题总结 C语言实现_第13张图片

leetcode 83. 删除排序链表中的重复元素

考研数据结构常考的代码题总结 C语言实现_第14张图片

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* deleteDuplicates(struct ListNode* head){
    if(head == NULL || head->next == NULL){
        return head;
    }
    struct ListNode* p = head;
    while (p->next != NULL) {
        if(p->next->val == p->val){
            p->next = p->next->next;
        } else {
            p = p->next;
        }
    }
    return head;
}

考研数据结构常考的代码题总结 C语言实现_第15张图片

PAT 6-5 链式表操作集 (20 分)

考研数据结构常考的代码题总结 C语言实现_第16张图片

/**
*Created by salmon on 2021-9-16 22:07.
**/

#include 
#include 

#define ERROR NULL
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

Position Find( List L, ElementType X );
List Insert( List L, ElementType X, Position P );
List Delete( List L, Position P );

int main()
{
    List L;
    ElementType X;
    Position P, tmp;
    int N;

    L = NULL;
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        L = Insert(L, X, L);
        if ( L==ERROR ) printf("Wrong Answer\n");
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        P = Find(L, X);
        if ( P == ERROR )
            printf("Finding Error: %d is not in.\n", X);
        else {
            L = Delete(L, P);
            printf("%d is found and deleted.\n", X);
            if ( L==ERROR )
                printf("Wrong Answer or Empty List.\n");
        }
    }
    L = Insert(L, X, NULL);
    if ( L==ERROR ) printf("Wrong Answer\n");
    else
        printf("%d is inserted as the last element.\n", X);
    P = (Position)malloc(sizeof(struct LNode));
    tmp = Insert(L, X, P);
    if ( tmp!=ERROR ) printf("Wrong Answer\n");
    tmp = Delete(L, P);
    if ( tmp!=ERROR ) printf("Wrong Answer\n");
    for ( P=L; P; P = P->Next ) printf("%d ", P->Data);
    return 0;
}

/* 你的代码将被嵌在这里 */
Position Find( List L, ElementType X ){//返回线性表中首次出现X的位置。若找不到则返回ERROR;
    Position res = L;
    while (L) {
        if(L->Data == X){
            return res;
        } else {
            L = L->Next;
            res = res->Next;
        }
    }
    return ERROR;
}
List Insert( List L, ElementType X, Position P ){ //将X插入在位置P指向的结点之前,返回链表的表头。如果参数P指向非法位置,
                                                    // 则打印“Wrong Position for Insertion”,返回ERROR;
    if(P < 0) {
        printf("Wrong Position for Insertion\n");
        return ERROR;
    }
    struct LNode *head = malloc(sizeof(struct LNode));
    head->Next = L;
    struct LNode *p = head;
    Position x = (Position)malloc(sizeof(struct LNode));
    x->Data = X;
    while (p) {
        if(p->Next == P){//P为没有加入一个虚拟的头结点的第一个结点下标 也可以这么想i指向-1,p指向0; 但使i=0时i总是在p前面一个位置
            struct LNode *temp = p->Next;
            p->Next = x;
            x->Next = temp;
            return head->Next;
        } else {
            p = p->Next;
        }
    }
    printf("Wrong Position for Insertion\n");
    return ERROR;
}
List Delete( List L, Position P ){ //将位置P的元素删除并返回链表的表头。若参数P指向非法位置,
                                    // 则打印“Wrong Position for Deletion”并返回ERROR
    if(P < 0) {
        printf("Wrong Position for Deletion\n");
        return ERROR;
    }
    struct LNode *head = malloc(sizeof(struct LNode));
    head->Next = L;
    struct LNode *p = head;
    while (p) {
        if (p->Next == P) {
           p->Next = p->Next->Next;
           return head->Next;
        } else {
            p = p->Next;
        }
    }
    printf("Wrong Position for Deletion\n");
    return ERROR;

}

考研数据结构常考的代码题总结 C语言实现_第17张图片

PAT 6-6 带头结点的链式表操作集 (20 分)

/**
*Created by salmon on 2021-9-17 22:05.
**/

#include 
#include 

#define ERROR NULL
typedef enum {false, true} bool;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
    ElementType Data;
    PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;

List MakeEmpty();
Position Find( List L, ElementType X );
bool Insert( List L, ElementType X, Position P );
bool Delete( List L, Position P );

int main()
{
    List L;
    ElementType X;
    Position P;
    int N;
    bool flag;

    L = MakeEmpty();
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        flag = Insert(L, X, L->Next);
        if ( flag==false ) printf("Wrong Answer\n");
    }
    scanf("%d", &N);
    while ( N-- ) {
        scanf("%d", &X);
        P = Find(L, X);
        if ( P == ERROR )
            printf("Finding Error: %d is not in.\n", X);
        else {
            flag = Delete(L, P);
            printf("%d is found and deleted.\n", X);
            if ( flag==false )
                printf("Wrong Answer.\n");
        }
    }
    flag = Insert(L, X, NULL);
    if ( flag==false ) printf("Wrong Answer\n");
    else
        printf("%d is inserted as the last element.\n", X);
    P = (Position)malloc(sizeof(struct LNode));
    flag = Insert(L, X, P);
    if ( flag==true ) printf("Wrong Answer\n");
    flag = Delete(L, P);
    if ( flag==true ) printf("Wrong Answer\n");
    for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data);
    return 0;
}
/* 你的代码将被嵌在这里 */
List MakeEmpty(){//创建并返回一个带头节点的空的线性表;
    List list = (List)malloc(sizeof(struct LNode));
    list->Next = NULL;
    return list;
}
Position Find( List L, ElementType X ){// 返回线性表中X的位置。若找不到则返回ERROR;
    Position p = L;
    while (p->Next) {//至于这里为什么是p->Next是因为在下方的if中访问了p的下一个节点的内容,如果p的下一个节点为空,会发生段错误
        if(p->Next->Data == X){
            return p->Next;
        } else {
            p = p->Next;
        }
    }
    return ERROR;
}
bool Insert( List L, ElementType X, Position P ){// 将X插入在位置P指向的结点之前,返回true。如果参数P指向非法位置,
    // 则打印“Wrong Position for Insertion”,返回false;
    Position p = L;
    Position x = (Position)malloc(sizeof(struct LNode));
    x->Data = X;
    while (p) {
        if(p->Next == P){
            p->Next = x;
            x->Next = P;
            return true;
        } else {
            p = p->Next;
        }
    }
    printf("Wrong Position for Insertion\n");
    return false;
}
bool Delete( List L, Position P ){  // 将位置P的元素删除并返回true。若参数P指向非法位置,
    // 则打印“Wrong Position for Deletion”并返回false。
    Position p = L;
    while (p) {
        if(p->Next == P){
            p->Next = p->Next->Next;
            return true;
        } else {
            p = p->Next;
        }
    }
    printf("Wrong Position for Deletion\n");
    return false;
}

考研数据结构常考的代码题总结 C语言实现_第18张图片

PAT 6-7 在一个数组中实现两个堆栈 (20 分)

考研数据结构常考的代码题总结 C语言实现_第19张图片

/**
*Created by salmon on 2021-9-18 22:13.
**/

#include 
#include 

#define ERROR 1e8
typedef int ElementType;
typedef enum { push, pop, end } Operation;
typedef enum { false, true } bool;
typedef int Position;
struct SNode {
    ElementType *Data;
    Position Top1, Top2;
    int MaxSize;
};
typedef struct SNode *Stack;

Stack CreateStack( int MaxSize );
bool Push( Stack S, ElementType X, int Tag );
ElementType Pop( Stack S, int Tag );

Operation GetOp();  /* details omitted */
void PrintStack( Stack S, int Tag ); /* details omitted */

int main()
{
    int N, Tag, X;
    Stack S;
    int done = 0;

    scanf("%d", &N);
    S = CreateStack(N);
    while ( !done ) {
        switch( GetOp() ) {
            case push:
                scanf("%d %d", &Tag, &X);
                if (!Push(S, X, Tag)) printf("Stack  %d is Full!\n", Tag);
                break;
                case pop:
                    scanf("%d", &Tag);
                    X = Pop(S, Tag);
                    if ( X==ERROR ) printf("Stack %d is Empty!\n", Tag);
                    break;
                    case end:
                        PrintStack(S, 1);
                        PrintStack(S, 2);
                        done = 1;
                        break;
        }
    }
    return 0;
}

/* 你的代码将被嵌在这里 */
Stack CreateStack( int MaxSize ){//两端各有一个栈
    Stack s = (Stack) malloc(sizeof(struct SNode));
    s->Data = (ElementType *) malloc(sizeof(ElementType)*MaxSize);
    s->MaxSize = MaxSize;
    s->Top1 = -1;
    s->Top2 = MaxSize;
    return s;
}
bool Push( Stack S, ElementType X, int Tag ){//tag表示对哪个栈进行处理
    if (S->Top1 + 1 == S->Top2) {
        printf("Stack Full\n");
        return false;
    }

    if(Tag == 1){
        S->Top1++;
        S->Data[S->Top1] = X;
    } else {
        S->Top2--;
        S->Data[S->Top2] = X;
    }
    return true;

}
ElementType Pop( Stack S, int Tag ){
    if ((S->Top1 == -1 && Tag == 1) || (S->Top2 == S->MaxSize && Tag == 2)) {
        printf("Stack %d Empty\n",Tag);
        return ERROR;
    }

    if(Tag == 1){
        return S->Data[S->Top1--];
    } else {
        return S->Data[S->Top2++];
    }
}

考研数据结构常考的代码题总结 C语言实现_第20张图片

PAT 6-8 求二叉树高度 (20 分) 递归与非递归方法

考研数据结构常考的代码题总结 C语言实现_第21张图片

int GetHeight( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
    int maxLeft = 0,maxRight = 0;
    if(BT == NULL){ //第一次,一直递归到此树叶子结点的孩子结点时停止,此时该结点为NULL所以高度为0
        return 0;
    } else { //以当前BT为根节点判断左子树高度和右子树高度谁更大
        maxLeft = GetHeight(BT->Left);
        maxRight = GetHeight(BT->Right);
        return (maxLeft > maxRight ? maxLeft + 1 : maxRight + 1); //此时已经计算完成一个叶结点,返回结点到它的双亲节点,显然高度要加1
    }
}

非递归算法求二叉树的高度,一般利用层次遍历的方法,初始化一个队列,定义一个中间变量来保存每次循环一开始的rear,如果front追上了rear则二叉树高度加1

int GetHeight( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
    if (BT == NULL) return 0;
    BinTree Queque[999];

    //初始化队列
    Queque[0] = BT;
    int front = 0, rear = 1,last = rear;
    int high = 0;

    while (front < rear) {
        if (Queque[front]->Left != NULL) {
            Queque[rear] = Queque[front]->Left;
            rear++;
        }
        if(Queque[front]->Right != NULL) {
            Queque[rear] = Queque[front]->Right;
            rear++;
        }
        front++;
        if(front == last){
            high++;
            last = rear;
        }
    }
    return high;
}

考研数据结构常考的代码题总结 C语言实现_第22张图片

PAT 6-10 二分查找 (20 分)(递归和迭代版本)

考研数据结构常考的代码题总结 C语言实现_第23张图片

Position trueBinarySearch( List L, ElementType X, Position low, Position high ){
    if(low > high) return NotFound;
    Position mid = (Position)((low + high) / 2);
    if (X < L->Data[mid]) {
        return trueBinarySearch(L,X,low,mid - 1);
    } else if (X > L->Data[mid]) {
        return trueBinarySearch(L,X,mid + 1,high);
    } else {
        return mid;
    }
}

Position BinarySearch( List L, ElementType X ){
    Position high = L->Last;
    Position low = 0;
    return trueBinarySearch(L,X,low,high);
}


Position BinarySearch( List L, ElementType X ){
    ElementType tag;
    Position low = 0;
    Position high = L -> Last;
    while (low <= high) {
        Position mid = (ElementType)((low + high) / 2);
        if (X < L->Data[mid]) {
            high = mid - 1;
        } else if (X > L->Data[mid]) {
            low = mid + 1;
        } else {
            return mid;
        }
    }
    return NotFound;
}

考研数据结构常考的代码题总结 C语言实现_第24张图片

PAT 6-9 二叉树的遍历 (25 分) 迭代和递归版本

考研数据结构常考的代码题总结 C语言实现_第25张图片

void InorderTraversal( BinTree BT ){//中序
    if (BT) {
        InorderTraversal(BT->Left);
        printf(" %c",BT->Data);
        InorderTraversal(BT->Right);
    }
}
void PreorderTraversal( BinTree BT ){
    if (BT) {
        printf(" %c",BT->Data);
        PreorderTraversal(BT->Left);
        PreorderTraversal(BT->Right);
    }
}
void PostorderTraversal( BinTree BT ){
    if (BT) {
        PostorderTraversal(BT->Left);
        PostorderTraversal(BT->Right);
        printf(" %c",BT->Data);
    }
}
void LevelorderTraversal( BinTree BT ){//层次遍历
    if (BT == NULL) return;
    BinTree Queque[999];

    //初始化队列
    Queque[0] = BT;
    int front = 0, rear = 1;

    while (front < rear) {
        if (Queque[front]->Left != NULL) {
            Queque[rear] = Queque[front]->Left;
            rear++;
        }
        if(Queque[front]->Right != NULL) {
            Queque[rear] = Queque[front]->Right;
            rear++;
        }
        printf(" %c",Queque[front]->Data);
        front++;
    }
}
BinTree assistStack[999];
int assistTop = -1;
void assistPush( BinTree BT ){
    if(assistTop >= 999) return;
    assistTop++;
    assistStack[assistTop] = BT;
}

BinTree assistPop(){
    if(assistTop <= -1) return NULL;
    return assistStack[assistTop--];
}

int assistStackIsEmpty(){
    if(assistTop <= -1) return -1; //-1为空
    else return 1;           //1为不空
}


BinTree Stack[999];
int top = -1;
void push( BinTree BT ){
    if(top >= 999) return;
    top++;
    Stack[top] = BT;
}

BinTree pop(){
    if(top <= -1) return NULL;
    return Stack[top--];
}

int stackIsEmpty(){
    if(top <= -1) return -1; //-1为空
    else return 1;           //1为不空
}

void InorderTraversal( BinTree BT ){//中序
    while (BT != NULL || stackIsEmpty() == 1) {
        while (BT != NULL) {
            push(BT);
            BT = BT->Left;
        }
        if (stackIsEmpty() == 1) {
            BT = pop();
            printf(" %c",BT->Data);
            BT = BT->Right;
        }
    }
}
void PreorderTraversal( BinTree BT ){
    if(BT == NULL) return;
    push(BT);
    while (stackIsEmpty() == 1) {
        BT = pop();
        printf(" %c",BT->Data);
        if(BT->Right != NULL){
            push(BT->Right);
        }
        if(BT->Left != NULL){
            push(BT->Left);
        }
    }
}
void PostorderTraversal( BinTree BT ){
    while (BT != NULL || assistStackIsEmpty() == 1) {
        while (BT != NULL) {
            assistPush(BT);
            push(BT);
            BT = BT->Right;
        }
        if(assistStackIsEmpty() == 1){
            BT = assistPop();
            BT = BT->Left;
        }
    }
    while (stackIsEmpty() == 1) {
        BinTree res = pop();
        printf(" %c",res->Data);
    }
}
void LevelorderTraversal( BinTree BT ){//层次遍历
    if (BT == NULL) return;
    BinTree Queque[999];

    //初始化队列
    Queque[0] = BT;
    int front = 0, rear = 1;

    while (front < rear) {
        if (Queque[front]->Left != NULL) {
            Queque[rear] = Queque[front]->Left;
            rear++;
        }
        if(Queque[front]->Right != NULL) {
            Queque[rear] = Queque[front]->Right;
            rear++;
        }
        printf(" %c",Queque[front]->Data);
        front++;
    }
}

参考博客:https://blog.csdn.net/dabusiGin/article/details/102736180?spm=1001.2014.3001.5501
考研数据结构常考的代码题总结 C语言实现_第26张图片
这里我们总结一下非递归版本的二叉树遍历:

  • 先序遍历:没什么难的,先右后左,输出根
  1. 定义一个栈
  2. 把根节点入栈
  3. 建立一个以栈不空为条件的循环
  4. 出栈,当前指针指向出栈的元素,并输出当前元素的内容
  5. 将该节点按照先右后左的顺序入栈
  6. 循环往复直到退出循环
  • 中序遍历:稍微有点东西,先访问到最左下角的结点,一边访问一遍入栈。到底后出栈,并输出当前结点的内容,如果当前有右节点那么接着访问该节点左孩子节点,否则出栈回到父节点
  1. 建立一个以当前指针不空或栈不空的循环
  2. 如果当前指针不为空,就入栈,并一直访问到最左节点的左孩子
  3. 如果栈不空就出栈并输出当前元素内容
  4. 访问右节点(这里比较巧妙的是,如果右节点为空,什么也不做,只是出栈回到父节点)
  5. 循环往复
  • 后序遍历:有些难,需要两个栈配合,与中序反着来。先一直访问到最右结点,一边访问一边同时入两个栈。到底后出栈,如果出栈结点有左孩子结点就接着访问该节点的右孩子,否则出栈回到父节点
  1. 建立一个以当前指针不空或栈不空的循环
  2. 如果当前指针不为空,就入双栈,并一直访问到最右节点的右孩子
  3. 如果辅助栈不空就出辅助栈
  4. 访问左节点(这里比较巧妙的是,如果右节点为空,什么也不做,只是出栈回到父节点)
  5. 循环往复
  6. 输出非辅助栈内的元素
  • 层序遍历:没啥好说的一个队列就完事

总的来说就是,前中后非递归遍历要利用好栈,用栈来代替递归中的回溯到父节点的功能。

PAT 6-11 先序输出叶结点 (15 分)

考研数据结构常考的代码题总结 C语言实现_第27张图片

/**
*Created by salmon on 2021-9-23 22:22.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

BinTree CreatBinTree(); /* 实现细节忽略 */
void PreorderPrintLeaves( BinTree BT );

int main()
{
    BinTree BT = CreatBinTree();
    printf("Leaf nodes are:");
    PreorderPrintLeaves(BT);
    printf("\n");

    return 0;
}
/* 你的代码将被嵌在这里 */
void PreorderPrintLeaves( BinTree BT ){
    if(!BT) return;
    if(BT->Left == NULL && BT->Right == NULL){
        printf(" %c",BT->Data);
        return;
    }
    if(BT->Left != NULL){
        return PreorderPrintLeaves(BT->Left);
    }
    if(BT->Right != NULL){
        return PreorderPrintLeaves(BT->Right);
    }
}

考研数据结构常考的代码题总结 C语言实现_第28张图片

PAT 6-12 二叉搜索树的操作集 (30 分) 递归与非递归版本

考研数据结构常考的代码题总结 C语言实现_第29张图片

BinTree Insert( BinTree BST, ElementType X ){
    if (!BST) { //当递归到正确位置时创造结点
        BST = (BinTree) malloc(sizeof(struct TNode));
        BST->Right = NULL;
        BST->Left = NULL;
        BST->Data = X;
    }
    if(BST->Data > X) BST->Left = Insert(BST->Left,X); //根据二叉搜索树的特性,小了往左,大了往右,一直到叶节点为止
    if(BST->Data < X) BST->Right = Insert(BST->Right,X);
    return BST;
}
/**
 * 二叉搜索树的删除有三种情况:
 *                  1.被删除节点为叶子结点,此时什么都不用做,直接删除
 *                  2.被删除节点只有左结点或右结点,用子结点代替即可
 *                  3.被删除节点有两个孩子,那么我们使用它的后继(或前驱)结点替换它,并且删除前驱结点
 * @param BST
 * @param X
 * @return
 */
BinTree Delete( BinTree BST, ElementType X ){

    if(!BST){
        printf("Not Found\n");
        return BST;
    }
    if(BST->Data < X) BST->Right = Delete(BST->Right,X);
    if(BST->Data > X) BST->Left = Delete(BST->Left,X);
    if(BST->Data == X){
        if(BST->Left == NULL || BST->Right == NULL){
            BST = BST->Left == NULL ? BST->Right : BST->Left;
        } else {
            Position temp = FindMin(BST->Right);
            BST->Data = temp->Data; //注意只是把内容替换,务必不要整个替换节点
            BST->Right = Delete(BST->Right,BST->Data);//删除结点
        }
    }
    return BST;

}
Position Find( BinTree BST, ElementType X ){
    if(!BST) return NULL;
    if(BST->Data == X) return BST;
    else if(BST->Data > X) return Find(BST->Left,X);
    else return Find(BST->Right,X);
}
Position FindMin( BinTree BST ){
    if(!BST) return NULL;
    if (BST->Left) {
       return FindMin(BST->Left);
    }
    return BST;
}
Position FindMax( BinTree BST ){
    if(!BST) return NULL;
    if (BST->Right) {
        return FindMax(BST->Right);
    }
    return BST;
}
Position Find(BinTree BST, ElementType X){
	while (BST){
		if (X > BST->Data) BST = BST->Right;
		else if (X < BST->Data) BST = BST->Left;//此处一定要加else,下同
		else if(X==BST->Data) return BST;
	}
	return NULL;
}

Position FindMin( BinTree BST ){
    if(!BST) return NULL;
    while(BST->Left) BST = BST->Left;
    return BST;
}

Position FindMax( BinTree BST ){
    if(!BST) return NULL;
    while(BST->Right) BST = BST->Right;
    return BST;
}

BinTree Insert( BinTree BST, ElementType X ){
    if(!BST){
        BST = (BinTree)malloc(sizeof(struct TNode));
        BST->Data = X;
        BST->Left = NULL;
        BST->Right = NULL;
    }
    if(X < BST->Data) BST->Left = Insert(BST->Left, X);
    if(X > BST->Data) BST->Right = Insert(BST->Right, X);
    return BST;
}

BinTree Delete( BinTree BST, ElementType X ){
    Position temp;
    if(!BST){
        printf("Not Found\n");
        return BST;
    }
    if(X < BST->Data) BST->Left = Delete(BST->Left, X);
    if(X > BST->Data) BST->Right = Delete(BST->Right, X);
    if(X==BST->Data){
        if(BST->Left&&BST->Right){
            temp = FindMin(BST->Right);
            BST->Data = temp->Data;
            BST->Right = Delete(BST->Right, BST->Data);
        }
        else{
            if(BST->Left) BST = BST->Left;
            else BST = BST->Right;
        }
    }
    return BST;
}

考研数据结构常考的代码题总结 C语言实现_第30张图片

求二叉树中度为0、1、2结点的个数

#include 

/**
*Created by salmon on 2021-9-25 22:30.
**/
typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

int degree0Count = 0;
int degree1Count = 0;
int degree2Count = 0;


void nodeCountOfVariousDegree( BinTree BT ,int &degree0Count, int &degree1Count, int &degree2Count ){
    if(!BT) return;
    if(BT->Left == NULL && BT->Right == NULL){
        degree0Count++;
    }else if((BT->Left == NULL && BT->Right != NULL) || (BT->Right == NULL && BT->Left != NULL)){
        degree1Count++;
    }else if(BT->Left != NULL && BT->Right != NULL){
        degree2Count++;
    }
    if(BT->Left != NULL){
         nodeCountOfVariousDegree(BT->Left,degree0Count,degree1Count,degree2Count);
    }
    if(BT->Right != NULL){
         nodeCountOfVariousDegree(BT->Right,degree0Count,degree1Count,degree2Count);
    }
}

int main(){
    BinTree binTree = (BinTree)malloc(sizeof(struct TNode));
//    binTree->Left = NULL;
    binTree->Left = (BinTree)malloc(sizeof(struct TNode));
    binTree->Left->Left = NULL;
    binTree->Left->Right = NULL;
//    binTree->Right = (BinTree)malloc(sizeof(struct TNode));
//    binTree->Right->Left = NULL;
//    binTree->Right->Right = NULL;
    binTree->Right == NULL;
    nodeCountOfVariousDegree(binTree,degree0Count,degree1Count,degree2Count);
    printf("%d\n",degree0Count);
    printf("%d\n",degree1Count);
    printf("%d\n",degree2Count);

}


---------------以下只给出伪代码--------------------

二叉树自下而上,从右到左的层次遍历

/**
*Created by salmon on 2021-9-29 22:50.
**/
#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};
void SpecialLevelTraversebt(BinTree BT){ //即与正常的层次遍历算法的输出反着来,多添加一个栈来实现
    if(BT == NULL) return;
    Queue Q = initQueue();
    Stack S = initStack();
    EnQueue(BT);
    while ( !isEmpty(Q) ) {
        BinTree temp = DeQueue();
        Push(temp);
        if(temp->Left){
            EnQueue(temp->Left);
        }
        if(temp->Right){
            EnQueue(temp->Right);
        }
    }

    while ( !isEmpty(S) ){
        BinTree res = Pop(S);
        visit(res->Data);
    }
}

判断二叉树是否为完全二叉树

/**
*Created by salmon on 2021-9-29 23:12.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

/**
 * 具体思路为,进行普通的层序遍历,唯一不同的是即使当前结点为叶子结点,我们依旧把左右孩子入队列,
 * 当遍历到空节点时,说明已经遍历到第一个叶子结点的孩子结点,那么从这里开始队列中的剩余结点均为空结点,
 * 所以如果剩余结点有不为空的结点,那么就不是完全二叉树
 * @param BT 
 * @return 
 */
bool isCompleteTree(BinTree BT){
    if(!BT) return true; //如果树为空,是完全二叉树
    Queue Q = InitQueue();
    EnQueue(BT);
    while ( !isEmpty(Q) ){
        BinTree BT = DeQueue(Q);
        if(BT){
            EnQueue(BT->Left);
            EnQueue(BT->Right);
        } else {
            while ( !isEmpty(Q) ){
                BinTree BT = DeQueue(Q);
                if(BT) return false;
            }
            return true;
        }
    }
}

将二叉树所有结点的左右子树交换

/**
*Created by salmon on 2021-9-29 23:30.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

/**
 * 要自底向上的交换,递归方法类似于后序遍历
 * @param BT 
 */
void swap(BinTree BT){
    if(BT){
        swap(BT->Left);
        swap(BT->Right);
        BinTree temp = BT->Left;
        BT->Left = BT->Right;
        BT->Right = temp;
    }
}

删除二叉树中所有值为X的节点,以及它的左右子树

/**
*Created by salmon on 2021-10-1 00:23.
**/
#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

void delete(BinTree BT){
    if(BT){ //删除该树时应从底部开始删除,类似于后序遍历
        delete(BT->Left);
        delete(BT->Right);
        free(BT);
    }
}

/**
 * 比较方便的思路是层次遍历整棵树,如果找到X则删除它以及以它为根节点的子树
 * @param BT 
 * @param X 
 */
void searchAndDelete(BinTree BT,ElementType X){
    if(BT == NULL) return;
    if(BT->Data == X) return delete(BT);

    Queue Q = initQueue();
    EnQueue(BT);
    while ( !isEmpty(Q) ){
        BinTree temp = DeQueue(Q);
        if(temp->Left){
            if(temp->Left->Data == X){ //查找时,我们让指针停留在父节点,用父节点的左右孩子来进行对比,这样有利于删除操作。
                delete(temp->Left);
                temp->Left = NULL;
            } else {
                EnQueue(temp->Left);
            }
        }
        if(temp->Right){
            if(temp->Right->Data == X){
                delete(temp->Right);
                temp->Right = NULL;
            } else {
                EnQueue(temp->Right);
            }
        }
    }
}

在二叉树中查找值为X的结点,并输出其所有的祖先结点

/**
*Created by salmon on 2021-10-3 23:48.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};

void SearchAncestorOfX(BiTree T, ElementType X){
    InitStack(S);
    BiTree p = T; //p为遍历指针
    BiTree record = NULL; //record为辅组指针,指向最近访问过的结点。

    while(p || !StackIsEmpty(S)) {
        if(p) {
            push(S, p);
            p = p->lchild; //左孩子不空,一直向左走
        } else { //向右
            GetTop(S,p); //读栈顶结点(非出栈)
            if(p->data == X) {//如果栈顶结点的值等于x
                pop(S,P);//先把当前结点pop了,因为只需要打印所有祖先
    
                while(!StackIsEmpty(S)) {//将剩下的祖先依次打印
                    pop(S, p);
                    visit(p); //访问该结点
                }
                return 0; //执行完毕返回
            }
    
            if(p->rchild && p->rchild != record) {//若右子树存在,且未被访问过
                p = p->rchild; //转向右
                push(S, p);
                p = p->lchild; //再走到最左
            } else {//否则,弹出结点
                pop(S, p);
                record = p; //记录最近访问过的结点
                p = NULL; //结点访问完毕后,重置p指针,不然该结点又会重新入栈
            }
        }
    }
}

求一个二叉树的宽度

此题有些异议,一些题目中的宽度是树每层结点个数的最大值,另一些题目中先将一颗树转换为完全二叉树(一层中相隔的结点之间有空位的话补上结点),宽度指转换后的树每层结点个数的最大值

/**
*Created by salmon on 2021-10-5 00:33.
**/

#include 
#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree Left;
    BinTree Right;
};


int GetWidth( BinTree BT ){ //在脑中想象一颗只有2层的满二叉树可以更好地理解
    if (BT == NULL) return 0;
    Queque Q = initQueue();//初始化队列
    EnQueque(BT);
    int front = 0, rear = 1,last = rear;
    int width = 1;

    while (front < rear) {
        BinTree curr = DeQueue();
        if ( curr -> Left != NULL ) {
            EnQueue(curr -> Left);
            rear++;
        }
        if( curr -> Right != NULL ) {
            EnQueue(curr -> Right);
            rear++;
        }
        front++;
        if(front == last){
            width = width < (rear - front) ? (rear - front) : width;
            last = rear;
        }
    }
    return width;
}

求以孩子兄弟表示法存储的树的叶子节点数

/**
*Created by salmon on 2021-10-10 23:29.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree firstChild;
    BinTree nextsibling;
};

int leaves(BinTree BT){
    if(BT == NULL){
        return 0;
    } else {
        if(BT->firstChild == NULL){
            return 1 + leaves(BT->nextsibling);
        } else {
            return leaves(BT->nextsibling) + leaves(BT->firstChild);
        }
    }
}

求以孩子兄弟表示法存储的树的深度

/**
*Created by salmon on 2021-10-10 23:40.
**/

#include 
#include 

typedef char ElementType;
typedef struct TNode *Position;
typedef Position BinTree;
struct TNode{
    ElementType Data;
    BinTree firstChild;
    BinTree nextsibling;
};

int Height(BinTree BT){
    if(BT == NULL){
        return 0;
    } else {
        int childHigh = Height(BT->firstChild);
        int broChildHigh = Height(BT->nextsibling);
        return childHigh + 1 > broChildHigh ? childHigh + 1 : broChildHigh;
    }
}

希尔排序

/**
*Created by salmon on 2021-10-8 23:41.
**/

#include 
/**
 * 希尔排序大多数流行的是三种写法,这里取第二种:其它几种可参考链接:https://wenku.baidu.com/view/aa8a4fd2b0717fd5360cdced.html
 * 希尔排序即将原数组s[]分割成多个以增量d为标准的数组,再对其进行直接插入排序 默认为非递减排序
 * 本程序使用第二种写法,也是大多数教科书上的写法,这种写法与我们所学的分组后进行直接插入排序不同
 * 此种是从数组第一个元素开始依次向后扫描,每次比较的都是相隔d个的元素,显然也是符合希尔排序逻辑的实现方式,只不过进行了化整体为部分的操作
 * @param s
 * @param n
 */
void shellSort( int s[], int n ) { //n为有效数组长度,实际数组长度为n+1,s[0]作为数据保存单元
    int i,j,d;    //d为增量,j为已有序数组的最后一个元素下标
    for (d = n / 2; d >= 1; d = d / 2) {
        for( i = d + 1; i <= n; i++ ) {   //数组下标从分好组的第二个元素开始进行直接插入排序,第一个元素默认形成了一个有序数列
            s[0] = s[i];    //保存当前参照元素
            for ( j = i - d; j > 0 && s[0] < s[j]; j = j - d )  {
                //自后向前扫描已有序数组,如果已有序数组中有大于当前参照元素的,就将该元素后移
                s[j + d] = s[j];
                //继续向前扫描,j向前移d个位置,当j小于或等于0时结束
            }
            s[j + d] = s[0];   //找到了应该插入的位置的前一个位置
        }
    }
}


int main()
{
    int a[11],i;    /*定义数组及变量为基本整型*/
    printf("请输入 10 个数据:\n");
    for(i=1;i<=10;i++)
        scanf("%d",&a[i]);    /*从键盘中输入10个数据*/
        shellSort(a, 10);    /* 调用 shsort()函数*/
        printf("排序后的顺序是:\n");
        for(i=1;i<=10;i++){
            printf("%5d",a[i]);    /*输出排序后的数组*/
        }
            return 0;
}

即以如图顺序遍历:
考研数据结构常考的代码题总结 C语言实现_第31张图片

快速排序

/**
*Created by salmon on 2021-10-12 23:15.
**/

#include 
void QuickSort(int *, int, int); /*现在只需要定义一个函数, 不用交换还省了一个函数, 减少了代码量*/

int main()
{
    int i; //循环变量
    int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
    QuickSort(a, 0, 20); /*引用起来很简单, 0为第一个元素的下标, 20为最后一个元素的下标*/
    printf("最终排序结果为:\n");

    for (i=0; i<21; ++i)
    {
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

void QuickSort (int *a, int low, int high) {
    int i = low;
    int j = high;
    int key = a[low]; //把比较值保存起来,有的书上是使用a[0]保存起来,以你报考学校参考书为准
    if (low >= high) return;

    while (low < high) {
        while (low < high && key <= a[high]) {
            high--;
        }
        if (low != high) {
            a[low] = a[high];
            low++;
        }
        while (low < high && key >= a[low]) {
            low++;
        }
        if (low != high) {
            a[high] = a[low];
            high--;
        }
    }

    //此时low == high ,已经找到key的最终位置
    a[low] = key; //此时以key为分界线将序列分成左右两部分
    QuickSort(a, i, low - 1); //用同样的方式对分出来的左边的部分进行同上的做法
    QuickSort(a, low + 1, j); //用同样的方式对分出来的右边的部分进行同上的做法
}

结果:在这里插入图片描述

冒泡排序

/**
*Created by salmon on 2021-10-13 23:42.
**/
#include 

void BubbleSort( int num[], int length ){ //num为传入的数组,length为数组长度,这里用从后往前冒泡
    for (int i = 0; i < length; i++) {
        int flag = 0;
        for (int j = length - 1; j > i; j--) {
            if(num[j] < num[j - 1]){
                int temp = num[j - 1];
                num[j - 1] = num[j];
                num[j] = temp;
                flag++;
            }
        }
        if(flag == 0){
            break;
        }
    }
}

int main()
{
    int i;
    int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
    BubbleSort(a, 21);
    printf("最终排序结果为:\n");

    for (i=0; i < 21; ++i){
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

归并排序

/**
*Created by salmon on 2021-10-23 00:40.
**/

#include 
#define Maxsize 100

/**
 * 将num[low....mid]与num[mid + 1 ...high]合并成一个有序数组,升序
 * @param num
 * @param low
 * @param mid
 * @param high
 */
void merge(int num[],int low,int mid,int high){
    int assist[Maxsize]; //定义一个辅助数组
    int i,j,cur;
    for (cur = low; cur <= high ; ++cur) {
        assist[cur] = num[cur];    //将A中数组复制到辅助数组中
    }
    for (i = low,j = mid + 1,cur = i; i <= mid && j <= high; cur++) { //比较两个数组,将较小的元素移动到左边
        if(assist[i] <= assist[j]){
            num[cur] = assist[i];
            i++;
        } else {
            num[cur] = assist[j];
            j++;
        }
    }
    
    //以下是当两个中有某一个数组率先扫描完成时所需要做的操作,即将剩余数按顺序放入到原数组中
    while (i <= mid) {
        num[cur] = assist[i];
        cur++;
        i++;
    }
    while (j <= high) {
        num[cur] = assist[j];
        cur++;
        j++;
    }
}

void mergeSort(int num[],int low, int high){
    if(low < high){
        int mid = (low + high) / 2;
        mergeSort(num,low,mid);
        mergeSort(num,mid + 1,high);
        merge(num,low,mid,high);
    }
}

简单选择排序

/**
*Created by salmon on 2021-10-15 23:58.
**/
#include 


void SelectSort(int a[],int length){ //选择排序
    int mixIndex,temp;
    int i,j;
    for(i = 0; i < length - 1; i++){ //每次循环数组,找出最小的元素,放在前面,前面的即为排序好的
        mixIndex = i; //假设最小元素的下标
        for(j = i + 1; j < length; j++){ //将上面假设的最小元素与数组比较,交换出最小的元素的下标
            if(a[j] < a[mixIndex])
                mixIndex = j;
        }
        if(i != mixIndex) {
            temp = a[i];
            a[i] = a[mixIndex];
            a[mixIndex] = temp;
        }
    }
}

int main()
{
    int i;
    int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
    SelectSort(a, 21);
    printf("最终排序结果为:\n");

    for (i=0; i < 21; ++i){
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

由二分查找优化的直接插入排序

/**
*Created by salmon on 2021-10-20 23:54.
**/

#include 

//二分查找过程,查找key应插入的位置
int binarySearch(int num[], int key, int low, int high) {
    int mid = -1;
    //循环直到low>high,此时low即为要插入的位置
    while (low <= high) {
        mid = (low + high) / 2;
        if (key <= num[mid])
            high = mid - 1;
        else
            low = mid + 1;
    }
    return low;
}

//使用二分查找改进插入排序,使之最坏情况下时间复杂度为Θ(nlgn)
void binInsertionSort(int num[], int n) {
    for (int i = 1; i < n; i++) {
        int key = num[i];
        int index = binarySearch(num, key, 0, i);
        if (index != i) {
            //如果需要移动,则往后移动一个位置,把位置腾出来
            for (int j = i - 1; j >= index; j--) {
                num[j + 1] = num[j];
            }
            //把A[i]放到正确的位置
            num[index] = key;
        }
    }
}

int main()
{
    int i;
    int a[] = {900, 2, -58, 3, 34, 5, 76, 7, 32, 4, 43, 9, 1, 56, 8,-70, 635, -234, 532, 543, 2500};
    binInsertionSort(a, 21);
    printf("最终排序结果为:\n");

    for (i=0; i < 21; ++i){
        printf("%d ", a[i]);
    }
    printf("\n");
    return 0;
}

带头结点链表,将小于第一个元素的结点放在其前面,大于放在后面

/**
*Created by salmon on 2021-10-24 23:24.
**/

#include 
#include 
//带头结点链表,将小于第一个元素的结点放在其前面,大于放在后面
typedef int ElementType;
typedef struct Node *PtrToNode;
struct Node {
    ElementType data;
    PtrToNode   next;
};
typedef PtrToNode List;

void change( List L ){
    if(L -> next == NULL)	return;

    List p, end, first, pre;//end是末尾指针
    first = L -> next;	    //first指向L单链表的第一个元素
    p = first -> next;  	//p指向遍历当前结点
    pre = first;            //pre指向p的前一个结点

    while ( p ) {	//遍历单链表
        end = p->next;
        if(p -> data < first -> data){	//遇到比第一个元素小的则头插法插入
            pre->next = end;
            p->next = L->next;
            L->next = p;
            p = end;
        } else {	//其他则继续往后遍历
            p = p->next;
            pre = pre->next;
        }
    }
}

判断一颗树是否对称

/**
*Created by salmon on 2021-10-24 23:58.
**/


Definition for a binary tree node.
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
};


bool traversal(struct TreeNode* left,struct TreeNode *right){
    if(left == NULL && right == NULL){
        return true;
    }
    if(left == NULL || right == NULL) {
        return false;
    }
    if(left->val != right-> val) {
        return false;
    }

    return traversal(left->left, right->right) && traversal(left->right, right->left);
}

bool isSymmetric(struct TreeNode* root){
    if (root == NULL) {
        return true;
    }
    return traversal(root->left, root->right);
}

-------------------一些零碎的知识点-----------------------

二叉树在线索化后,仍不能有效求解的问题

考研数据结构常考的代码题总结 C语言实现_第32张图片
考研数据结构常考的代码题总结 C语言实现_第33张图片

存储结构的相关问题

  • 数据的逻辑结构包括:集合、线性结构、树形结构、图状结构或网状结构。
  • 数据的存储结构(物理结构)包括:顺序存储、链式存储、索引存储和散列存储。

考研数据结构常考的代码题总结 C语言实现_第34张图片

你可能感兴趣的:(PAT,算法,数据结构,算法,链表)