郑州轻工业大学2022-2023(2)数据结构题目集(精简版)

6-1 线性表元素的区间删除

List Delete(List L, ElementType minD, ElementType maxD) {
    
    
    int i, p = 0;
    for (i = 0; i <= L->Last; i++) {
    
    
        if (L->Data[i] <= minD || L->Data[i] >= maxD) {
    
    
            L->Data[p++] = L->Data[i];
        }
    }
    L->Last = p - 1;
    return L;
}

6-2 有序表的插入

void ListInsertSort(SqList *L, DataType x) {
    
    
    int i;
    int temp = 1;

    for (i = 0; L->items[i] < x; i++) {
    
    
        temp++;
    }

    ListInsert(L, temp, x);
}

6-3 合并两个有序数组

void merge(int *a, int m, int *b, int n, int *c) {
    int i, j, k;
    while (i < m && j < n) {
        if (a[i] < b[j])
            c[k++] = a[i++];
        else
            c[k++] = b[j++];
    }
    while (i < m) {
        c[k++] = a[i++];
    }
    while (j < n) {
        c[k++] = b[j++];
    }
}

6-4 顺序表操作集

List MakeEmpty() {
    
    
    List list;
    list = (List) malloc(sizeof(struct LNode));
    list->Last = -1;
    return list;
}

Position Find(List L, ElementType X) {
    
    
    int i;
    for (i = 0; i < MAXSIZE; i++) {
    
    
        if (L->Data[i] == X)
            return i;
    }
    return ERROR;
}

bool Insert(List L, ElementType X, Position P) {
    
    
    int i;

    if (L->Last == MAXSIZE - 1) {
    
    
        printf("FULL");
        return false;
    }

    if (P < 0 || P > L->Last + 1) {
    
    
        printf("ILLEGAL POSITION");
        return false;
    }

    for (i = L->Last; i >= P; i--) {
    
    
        L->Data[i + 1] = L->Data[i];
    }
    L->Data[P] = X;
    L->Last++;
    return true;

}

bool Delete(List L, Position P) {
    
    
    int i;

    if (P < 0 || P > L->Last) {
    
    
        printf("POSITION %d EMPTY", P);
        return false;
    }

    for (i = P; i < L->Last; i++) {
    
    
        L->Data[i] = L->Data[i + 1];
    }
    L->Last--;

    return true;
}

6-5 递增的整数序列链表的插入

List Insert(List L, ElementType X) {
    
    
    List p, s;
    p = L;
    s = (List) malloc(sizeof(struct Node));
    s->Data = X;

    while (p->Next && p->Next->Data < X) {
    
    
        p = p->Next;
    }
    s->Next = p->Next;
    p->Next = s;

    return L;
}

6-6 删除单链表偶数节点

struct ListNode *createlist() {
    
    
    int m;
    struct ListNode *p, *s, *l;
    p = (struct ListNode *) malloc(sizeof(struct ListNode));

    scanf("%d", &m);
    if (m == -1)
        return NULL;
    p->data = m;
    p->next = NULL;
    s = p;

    while (1) {
    
    
        scanf("%d", &m);
        if (m == -1)
            break;
        l = (struct ListNode *) malloc(sizeof(struct ListNode));
        l->data = m;
        l->next = NULL;
        s->next = l;
        s = l;
    }
    return p;

}

struct ListNode *deleteeven(struct ListNode *head) {
    
    
    struct ListNode *p = NULL, *s = NULL;

    while (head && head->data % 2 == 0) {
    
    
        p = head;
        head = head->next;
        free(p);
    }
    if (head == NULL)
        return NULL;
    s = head;
    while (s->next) {
    
    
        if (s->next->data % 2 == 0)
            s->next = s->next->next;
        else
            s = s->next;
    }
    return head;
}

6-7 逆序数据建立链表

struct ListNode *createlist() {
    
    
    int m;
    struct ListNode *head, *p;
    head = (struct ListNode *) malloc(sizeof(struct ListNode));
    head->next = NULL;

    while (1) {
    
    
        scanf("%d", &m);
        if (m == -1)
            break;
        p = (struct ListNode *) malloc(sizeof(struct ListNode));
        p->next = head->next;
        p->data = m;
        head->next = p;
    }
    return head->next;
}

6-8 求链表的倒数第m个元素

ElementType Find(List L, int m) {
    
    
    int i;
    PtrToNode p, s;
    p = s = L;

    for (i = 0; i < m; i++) {
    
    
        p = p->Next;
        if (!p)
            return ERROR;
    }
    while (p) {
    
    
        s = s->Next;
        p = p->Next;
    }

    return s->Data;
}

6-9 两个有序链表序列的合并

List Merge( List L1, List L2 )
{
    List pa,pb,pc;
    pa=L1->Next;
    pb=L2->Next;
    List L=(List)malloc(sizeof(List));
    pc=L;
    
    while(pa&&pb)
    {
        if(pa->Data>pb->Data)
        {
            pc->Next=pb;
            pb=pb->Next;
        }
        else{
            pc->Next=pa;
            pa=pa->Next;
        }
        pc=pc->Next;
    }
    
    if(pa)
        pc->Next = pa;
    if(pb)
        pc->Next = pb;
    L1->Next=NULL;
    L2->Next=NULL;
    
    return L;
}

6-10 二叉树的遍历

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) {
    
    
    BinTree B[100];//结构体数组
    BinTree T;
    int i = 0, j = 0;
    if (!BT)return;//树为空,返回
    if (BT)//不为空
    {
    
    
        B[i++] = BT;//根节点入队
        while (i != j)//队列不空
        {
    
    
            T = B[j++];//出队
            printf(" %c", T->Data);
            if (T->Left) B[i++] = T->Left;
            if (T->Right) B[i++] = T->Right;
        }
    }
} 

6-11 二叉树的非递归遍历

void InorderTraversal( BinTree BT ){
    
    //中序遍历
    BinTree T=BT;
    Stack S =CreateStack();
    while(T||!IsEmpty(S)){
    
    
        while(T!=NULL){
    
    
            Push(S,T);
            T=T->Left;
        }
        T=Pop(S);
        printf(" %c",T->Data);
        T=T->Right;
    }
}
void PreorderTraversal( BinTree BT ){
    
    //先序遍历
    BinTree T=BT;
    Stack S =CreateStack();
    while(T||!IsEmpty(S)){
    
    
        while(T!=NULL){
    
    
            Push(S,T);
            printf(" %c",T->Data);
            T=T->Left;
        }
        T=Pop(S);
        T=T->Right;
    }
}
void PostorderTraversal( BinTree BT ){
    
    //后序遍历
    BinTree T=BT;
    Stack S =CreateStack();
    while(T||!IsEmpty(S)){
    
    
        while(T!=NULL){
    
    
            T->flag=0;
            Push(S,T);
            T=T->Left;
        }
        T=Peek(S);
        if(T->flag==0){
    
    
            T->flag++;
            T=T->Right;
        }
        else{
    
    
            T=Pop(S);
            printf(" %c",T->Data);
            T=NULL;
        }
    }
}

6-12 求二叉树高度

int GetHeight(BinTree BT) {
    
    
    int lNum, rNum, Height;
    if (BT) {
    
    
        lNum = GetHeight(BT->Left);
        rNum = GetHeight(BT->Right);
        if (lNum > rNum)
            Height = lNum;
        else
            Height = rNum;
        return Height + 1;
    } else {
    
    
        return 0;
    }
}

6-13 邻接矩阵存储图的深度优先遍历

void DFS(MGraph Graph, Vertex V, void (*Visit)(Vertex)) {
    
    
    Vertex i;
    Visit(V);
    Visited[V] = true;
    for (int i = 0; i < Graph->Nv; i++) {
    
    
        if (Graph->G[V][i] == 1 && !Visited[i]) {
    
    
            DFS(Graph, i, Visit);//进行递归
        }
    }
}

6-14 邻接表存储图的广度优先遍历

void BFS(LGraph Graph, Vertex S, void (*Visit)(Vertex)) {
    
    
    Visited[S] = true;//标记起始点
    Visit(S);
    int queue[1000], front = 0, rear = 0;
    queue[rear++] = S;//起始点入队列
    PtrToAdjVNode temp;//temp就代表当前点的邻接点的下标
    while (front < rear) {
    
    //队伍不为空
        temp = Graph->G[queue[front++]].FirstEdge;
        while (temp) {
    
    
            int p = temp->AdjV;//把temp中的下标提取出来
            if (!Visited[p]) {
    
    //如果p点没有被标记的话
                Visited[p] = true;
                Visit(p);
                queue[rear++] = p;//储存在队列中
            }
            temp = temp->Next;//指向下一个邻接点
        }
    }
}

7-1 一元多项式的乘法与加法运算

#include <stdio.h>
#include <stdlib.h>

typedef int ElementType;
typedef struct LNode *List;

struct LNode {
    ElementType coe;//系数
    ElementType exp;//指数
    List Next;//下一个节点
};

void Insert(List L, ElementType coe, ElementType exp);//插入
List Multi(List p1, List p2);//乘法
List Plus(List p1, List p2);//加法
int compare(List p1, List p2);//比较系数大小

int main() {
    List p1, p2;
    List p;
    int num1, num2, coe, exp;
    int i;
    p1 = (List) malloc(sizeof(struct LNode));
    p2 = (List) malloc(sizeof(struct LNode));
    p1->Next = NULL;
    p2->Next = NULL;

    scanf("%d", &num1);
    for (i = 0; i < num1; i++) {
        scanf("%d %d", &coe, &exp);
        Insert(p1, coe, exp);
    }
    scanf("%d", &num2);
    for (i = 0; i < num2; i++) {
        scanf("%d %d", &coe, &exp);
        Insert(p2, coe, exp);
    }
    //乘法运算
    p = Multi(p1->Next, p2->Next);
    while (p) {
        if (p->Next != NULL) {
            printf("%d %d ", p->coe, p->exp);//非最后一个节点,不换行打印,后接空格
        } else {
            printf("%d %d\n", p->coe, p->exp);//最后一个节点,换行打印
        }
        p = p->Next;
    }
    //加法运算
    p = Plus(p1->Next, p2->Next);
    if (p) {
        while (p) {
            if (p->Next != NULL) {
                printf("%d %d ", p->coe, p->exp);
            } else {
                printf("%d %d\n", p->coe, p->exp);
            }
            p = p->Next;
        }
    } else {//防止出现p1,p2抵消为零的情况
        printf("0 0\n");
    }
    return 0;
}

/**
 * 向链表中添加元素
 * @param L 需要添加的链表
 * @param coefficient 系数
 * @param exponent 指数
 */
void Insert(List L, ElementType coe, ElementType exp) {
    List s, p;
    p = L;

    while (p->Next)//找到最后一个节点
        p = p->Next;

    s = (List) malloc(sizeof(struct LNode));
    s->Next = NULL;
    s->coe = coe;
    s->exp = exp;

    p->Next = s;
}

/**
 * 两个多项式相乘
 * @param p1 代表多项式1的链表
 * @param p2 代表多项式2的链表
 * @return p 相乘后生成的新链表
 */
List Multi(List p1, List p2) {
    List p, p1a, p2a, s;
    int flag = 1;
    p = (List) malloc(sizeof(struct LNode));
    p->Next = NULL;
    p1a = p1;

    while (p1a) {
        p2a = p2;//确保p1多项式中的每一项可以与p2多项式中的每一项分别相乘
        s = (List) malloc(sizeof(struct LNode));
        s->Next = NULL;

        while (p2a) {//与p2多项式中的每一项分别相乘
            Insert(s, p1a->coe * p2a->coe, p1a->exp + p2a->exp);
            p2a = p2a->Next;
        }
        s = s->Next;

        if (flag == 1) {
            p = p->Next;
            /*
             * 如果是p1第一项与p2每一项相乘,那么先将链表p向后移一位,将头结点屏蔽
             * 因为默认初始化的P1头结点有默认的exp = 0,coe = 0,这两个数据是多余的
             * 如果不后移,那么头结点默认的数值0将会一直尾随整个乘法运算,导致最后的结果后面多两个0 0
             */
            flag = 0;

        }
        p = Plus(p, s);//相加,确保同类项合并
        p1a = p1a->Next;
        free(s);
    }

    return p;
}

/**
 * 比较两多项式指数大小
 * @param p1 代表多项式1的链表
 * @param p2 代表多项式2的链表
 * @return 返回值为0时表示两指数相同,可以进行加法运算
 */
int compare(List p1, List p2) {
    if (p1->exp > p2->exp)
        return 1;//p1指数大
    else if (p1->exp < p2->exp)
        return -1;//p1指数小
    else
        return 0;//指数相同
}

/**
 * 两个多项式相加
 * @param p1 代表多项式1的链表
 * @param p2 代表多项式2的链表
 * @return p 相加后生成的新链表
 */
List Plus(List p1, List p2) {
    List p, p1a, p2a;
    int temp;
    p = (List) malloc(sizeof(struct LNode));
    p->Next = NULL;
    p1a = p1;
    p2a = p2;

    while (p1a && p2a) {
        temp = compare(p1a, p2a);
        //判断指数大小,同指数才可以运算
        switch (temp) {
            case 1:
                //当前p1a的指数大,将当前p1a的数据放入新链表
                Insert(p, p1a->coe, p1a->exp);
                p1a = p1a->Next;//p1a向后移动,p2a不改变
                break;
            case -1:
                //当前p2a的指数大,将当前p2a的数据放入新链表
                Insert(p, p2a->coe, p2a->exp);
                p2a = p2a->Next;//p2a向后移动,p1a不改变
                break;
            case 0:
                //指数相同,进行运算
                if ((p1a->coe + p2a->coe) == 0) {
                    //系数为0,数据不放入新链表,直接将p1a和p2a后移
                    p1a = p1a->Next;
                    p2a = p2a->Next;
                } else {
                    //数据放入新链表,p1a和p2a后移
                    Insert(p, p1a->coe + p2a->coe, p2a->exp);
                    p1a = p1a->Next;
                    p2a = p2a->Next;
                }
                break;
            default:
                break;
        }
    }
    while (p1a) {
        //p1a的项数多,将剩余项放入链表
        Insert(p, p1a->coe, p1a->exp);
        p1a = p1a->Next;
    }
    while (p2a) {
        //p2a的项数多,将剩余项放入链表
        Insert(p, p2a->coe, p2a->exp);
        p2a = p2a->Next;
    }
    p = p->Next;
    return p;
}

7-2 符号配对

#include <stdio.h>
#include <stdlib.h>

#define Maxsize 105
typedef struct StackRecord *Stack;
struct StackRecord {
    int top;
    char *array;
};

Stack creat();//创建空栈
int cheekEmpty(Stack s);//判断栈是否为空
void push(Stack s, char x);//添加新元素
void pop(Stack s);//删除
char top(Stack s);//取出

char a[100];
char str[200];

int main() {
    int i, j = 0, flag = 0;
    char ch;
    Stack s = creat();

    while (gets(str)) {
        if (str[0] == '.' && !str[1])
            break;
        for( i=0; str[i]; i++){
            if(str[i]=='('||str[i]=='['||str[i]=='{'||str[i]==')'||str[i]=='}' ||str[i]==']')
                a[j++]=str[i];
            else if(str[i]=='/'&&str[i+1]=='*'){
                a[j++]='<';
                i++;
            }else if(str[i]=='*'&&str[i+1]=='/'){
                a[j++]='>';
                i++;
            }
        }
    }

    for (i = 0; i < j; i++) {
        if (a[i] == '(' || a[i] == '[' || a[i] == '{' || a[i] == '<') {
            push(s, a[i]);
        } else if (a[i] == ')') {
            if (s->top != -1 && top(s) == '(') {
                pop(s);
            } else {
                ch = a[i];
                flag = 1;
                break;
            }
        } else if (a[i] == ']') {
            if (s->top != -1 && top(s) == '[') pop(s);
            else {
                ch = a[i];
                flag = 1;
                break;
            }
        } else if (a[i] == '}') {
            if (s->top != -1 && top(s) == '{') pop(s);
            else {
                ch = a[i];
                flag = 1;
                break;
            }
        } else if (a[i] == '>') {
            if (s->top != -1 && top(s) == '<') pop(s);
            else {
                ch = a[i];
                flag = 1;
                break;
            }
        }
    }

    if (!flag && cheekEmpty(s)) {
        printf("YES\n");
    } else {
        printf("NO\n");
        if (!cheekEmpty(s)) {
            if (top(s) == '<') printf("/*-?\n");
            else printf("%c-?\n", top(s));
        } else {
            if (ch == '>') printf("?-*/\n");
            else printf("?-%c\n", ch);
        }
    }

    return 0;
}

/**
 * 创建新栈
 * @return
 */
Stack creat() {
    Stack s = (Stack) malloc(sizeof(struct StackRecord));
    s->top = -1;
    s->array = (char *) malloc(sizeof(char) * Maxsize);
    return s;
}

/**
 * 判断是否为空栈
 * @param s
 * @return
 */
int cheekEmpty(Stack s) {
    if (s->top == -1)
        return 1;
    else
        return 0;
}

/**
 *添加元素
 * @param s
 * @param x
 */
void push(Stack s, char x) {
    s->array[++(s->top)] = x;
}

/**
 *删除
 * @param s
 */
void pop(Stack s) {
    s->top--;
}

/**
 *取出
 * @param s
 */
char top(Stack s) {
    return s->array[s->top];
}

7-3 银行业务队列简单模拟

#include <stdio.h>

const int MAX = 1010;

int main() {

    int a[MAX], b[MAX], cnta, cntb;
    cnta = cntb = 0;
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        int temp;
        scanf("%d", &temp);
        if (temp % 2) a[++cnta] = temp;
        else b[++cntb] = temp;
    }
    int flag = 0, x = 1, y = 1;
    while (x <= cnta || y <= cntb) {
        if (x <= cnta) {
            if (flag++) printf(" ");
            printf("%d", a[x++]);
        }
        if (x <= cnta) {
            if (flag++) printf(" ");
            printf("%d", a[x++]);
        }
        if (y <= cntb) {
            if (flag++) printf(" ");
            printf("%d", b[y++]);
        }
    }
    return 0;
}

7-4 顺序存储的二叉树的最近的公共祖先问题

#include <stdio.h>

int find(int i, int j);

int main() {
    
    
    int n, i, j, m;
    int a[1000];
    scanf("%d", &n);
    for (i = 1; i <= n; i++) {
    
    
        scanf("%d", &a[i]);
    }
    scanf("%d %d", &i, &j);

    if (a[i] == 0)//查错
    {
    
    
        printf("ERROR: T[%d] is NULL\n", i);
        return 0;
    }
    if (a[j] == 0)//查错
    {
    
    
        printf("ERROR: T[%d] is NULL\n", j);
        return 0;
    }
    m = find(i, j);
    printf("%d %d", m, a[m]);
    return 0;
}

/**
 * 查找公共祖先,二分查找
 * @param i 
 * @param j 
 * @return 
 */
int find(int i, int j) {
    
    
    if (i == j) {
    
    
        return i;
    } else if (i > j) {
    
    
        return find(i / 2, j);
    } else if (i < j) {
    
    
        return find(i, j / 2);
    }
}

7-5 修理牧场

#include<stdio.h>
#include<stdlib.h>

typedef int ElemType;
typedef struct HuffmanTreeNode {
    
    
    ElemType data;  //哈夫曼树中节点的权值
    struct HuffmanTreeNode *left;
    struct HuffmanTreeNode *right;
} HuffmanTreeNode, *HuffmanTree;

HuffmanTree createHuffmanTree(ElemType arr[], int N) {
    
    
    HuffmanTree treeArr[N];
    HuffmanTree tree, pRoot = NULL;

    for (int i = 0; i < N; i++) {
    
      //初始化结构体指针数组,数组中每一个元素为一个结构体指针类型
        tree = (HuffmanTree) malloc(sizeof(HuffmanTreeNode));
        tree->data = arr[i];
        tree->left = tree->right = NULL;
        treeArr[i] = tree;
    }

    for (int i = 1; i < N; i++) {
    
      //进行 n-1 次循环建立哈夫曼树

        //k1为当前数组中第一个非空树的索引,k2为第二个非空树的索引
        int k1 = -1, k2 = 0;
        for (int j = 0; j < N; j++) {
    
    
            if (treeArr[j] != NULL && k1 == -1) {
    
    
                k1 = j;
                continue;
            }
            if (treeArr[j] != NULL) {
    
    
                k2 = j;
                break;
            }
        }
        //循环遍历当前数组,找出最小值索引k1,和次小值索引k2
        for (int j = k2; j < N; j++) {
    
    
            if (treeArr[j] != NULL) {
    
    
                if (treeArr[j]->data < treeArr[k1]->data) {
    
    //最小
                    k2 = k1;
                    k1 = j;
                } else if (treeArr[j]->data < treeArr[k2]->data) {
    
    //次小
                    k2 = j;
                }
            }
        }
        //由最小权值树和次最小权值树建立一棵新树,pRoot指向树根结点
        pRoot = (HuffmanTree) malloc(sizeof(HuffmanTreeNode));
        pRoot->data = treeArr[k1]->data + treeArr[k2]->data;
        pRoot->left = treeArr[k1];
        pRoot->right = treeArr[k2];

        treeArr[k1] = pRoot; //将新生成的数加入到数组中k1的位置
        treeArr[k2] = NULL; //k2位置为空
    }

    return pRoot;
}

ElemType calculateWeightLength(HuffmanTree ptrTree, int len) {
    
    
    if (ptrTree == NULL) {
    
     //空树返回0
        return 0;
    } else {
    
    
        if (ptrTree->left == NULL && ptrTree->right == NULL) {
    
     //访问到叶子节点
            return ptrTree->data * len;
        } else {
    
    
            return calculateWeightLength(ptrTree->left, len + 1) + calculateWeightLength(ptrTree->right, len + 1); //向下递归计算
        }
    }
}

int main() {
    
    
    ElemType arr[10001];
    int i = 0, N;
    scanf("%d", &N);

    while (i < N)
        scanf("%d", &arr[i++]);

    HuffmanTree pRoot = createHuffmanTree(arr, N);  //返回指向哈夫曼树根节点的指针

    printf("%d", calculateWeightLength(pRoot, 0));

    return 0;
}

7-6 公路村村通

#include <stdio.h>
#include <stdlib.h>

int fa[1005];

typedef struct {
    
    
    int l;
    int r;
    int weight;
} Node;

Node p[3005];
int n, m, sum, cnt;

int cmp(const void *a, const void *b) {
    
    
    Node *p1 = (Node *) a;
    Node *p2 = (Node *) b;
    return p1->weight - p2->weight;
}

int Find(int x) {
    
    
    return (x == fa[x]) ? (x) : (fa[x] = Find(fa[x]));
}

void Union(int x, int y) {
    
    
    fa[Find(x)] = Find(y);
}

int main() {
    
    
    scanf("%d %d", &n, &m);
    for (int i = 1; i <= n; i++)
        fa[i] = i;
    for (int i = 0; i < m; i++)
        scanf("%d %d %d", &p[i].l, &p[i].r, &p[i].weight);
    qsort(p, m, sizeof(Node), cmp);
    for (int i = 0; i < m; i++) {
    
    
        if (Find(p[i].l) != Find(p[i].r)) {
    
    
            sum += p[i].weight;
            Union(p[i].l, p[i].r);
            cnt++;
        }
        if (cnt == n - 1)
            break;
    }
    if (cnt == n - 1)
        printf("%d\n", sum);
    else
        printf("-1\n");
    return 0;
}

7-7 畅通工程之最低成本建设问题

#include <stdio.h>
#include <stdlib.h>

struct path {
    
    
    int a, b, c;
} p[3000];
int f[1001], n, m;

void init() {
    
    
    for (int i = 1; i <= n; i++) f[i] = i;
}

int getf(int k) {
    
    
    if (f[k] == k) return f[k];
    return f[k] = getf(f[k]);
}

int cmp(const void *a, const void *b) {
    
    
    return ((struct path *) a)->c - ((struct path *) b)->c;
}

int main() {
    
    
    scanf("%d%d", &n, &m);
    init();
    for (int i = 0; i < m; i++) {
    
    
        scanf("%d%d%d", &p[i].a, &p[i].b, &p[i].c);
    }
    qsort(p, m, sizeof(p[0]), cmp);
    int c = 0, ans = 0;
    for (int i = 0; i < m; i++) {
    
    
        if (getf(p[i].a) != getf(p[i].b)) {
    
    
            ans += p[i].c;
            c++;
            f[getf(p[i].a)] = getf(p[i].b);
        }
    }
    if (c < n - 1) printf("Impossible\n");
    else printf("%d\n", ans);
    return 0;
}

7-8 最短工期

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int n, m, ans;
int mp[100][100];
int l[100], q[100], t[100];

int main() {
    
    
    int a, b, c, head = 0, tail = 0;
    scanf("%d%d", &n, &m);
    memset(mp, -1, sizeof(mp));
    for (int i = 0; i < m; i++) {
    
    
        scanf("%d%d%d", &a, &b, &c);
        mp[a][b] = c;
        l[b]++;
    }
    for (int i = 0; i < n; i++) {
    
    
        if (!l[i]) {
    
    
            q[tail++] = i;
        }
    }
    while (head < tail) {
    
    
        int temp = q[head++];
        if (t[temp] > ans) ans = t[temp];
        for (int i = 0; i < n; i++) {
    
    
            if (mp[temp][i] != -1) {
    
    
                l[i]--;
                if (!l[i]) q[tail++] = i;
                if (t[i] < t[temp] + mp[temp][i]) {
    
    
                    t[i] = t[temp] + mp[temp][i];
                }
            }
        }
    }
    if (tail < n) printf("Impossible");
    else printf("%d", ans);
}

7-9 哈利·波特的考试

/**
 * 7-9 哈利·波特的考试
 *  最短路径     迪杰斯特拉算法
 */
#include<stdio.h>
#include<string.h>

#define maxInt 2147483647

typedef struct {
    
    
    int arcs[102][102];
    int vexnum, arcnum;
} MGraph;

int final[102];//final[w]=1表示求得顶点v0至vw的最短路径 
int D[102];  //记录v0到vi的当前最短路径长度
int P[102]; //记录v0到vi的当前最短路径vi的前驱

int i, u, j, m, v, min, w, k, a, b, c, min1 = 999999, max = -991111, p = 0;

void Dijkstra(MGraph G, int v0) {
    
    
    for (v = 0; v < G.vexnum; v++)    //初始化数据
    {
    
    
        final[v] = 0;            //全部顶点初始化为未知最短路径状态
        D[v] = G.arcs[v0][v];// 将与v0点有连线的顶点加上权值
        P[v] = -1;                //初始化路径数组P为-1
    }

    D[v0] = 0;  //v0至v0路径为0
    final[v0] = 1;    // v0至v0不需要求路径
    // 开始主循环,每次求得v0到某个v顶点的最短路径
    for (v = 1; v < G.vexnum; v++) {
    
    
        min = maxInt;    // 当前所知离v0顶点的最近距离
        for (w = 0; w < G.vexnum; w++) // 寻找离v0最近的顶点
        {
    
    
            if (!final[w] && D[w] < min) {
    
    
                k = w;
                min = D[w];    // w顶点离v0顶点更近
            }
        }
        final[k] = 1;    // 将目前找到的最近的顶点置为1
        for (w = 0; w < G.vexnum; w++) // 修正当前最短路径及距离
        {
    
    
            // 如果经过v顶点的路径比现在这条路径的长度短的话
            if (!final[w] && (min + G.arcs[k][w] < D[w])) {
    
     // 说明找到了更短的路径,修改D[w]和P[w]
                D[w] = min + G.arcs[k][w];  // 修改当前路径长度
                P[w] = k;
            }
        }
    }
}

int main() {
    
    
    MGraph G;
    memset(final, 0, sizeof(final));
    memset(D, 0x3f3f3f3f, sizeof(D));
    memset(G.arcs, 0x3f3f3f3f, sizeof(G.arcs));   //邻接矩阵一定要初始化
    scanf("%d %d", &G.vexnum, &m);
    for (i = 0; i < m; i++) {
    
    
        scanf("%d %d %d", &a, &b, &c);
        G.arcs[a - 1][b - 1] = c;
        G.arcs[b - 1][a - 1] = c;
    }
    for (u = 0; u < G.vexnum; u++) {
    
    
        max = -9999999;
        Dijkstra(G, u);
        for (j = 0; j < G.vexnum; j++) {
    
    
            if (D[j] > max)
                max = D[j];
        }
        if (max < min1) {
    
    
            min1 = max;
            p = u + 1;
        }

    }
    if (p == 0)
        printf("0");
    else
        printf("%d %d\n", p, min1);
    return 0;
}

7-10 旅游规划

/**
 * 7-10 旅游规划
 *  最短路径  弗洛伊德算法
 */

#include<stdio.h>

#define MAXN 500
#define ERROR -1
#define Infinite 65534

int N, M, S, D;//城市的个数 高速公路的条数 出发地 目的地
int Dist[MAXN][MAXN], Cost[MAXN][MAXN];//距离与花费矩阵
int dist[MAXN], cost[MAXN], visit[MAXN];//最短距离与花费 标记数组

void Inicialization(void);

void FindTheWay(void);

int FindMinWay(void);

int main() {
    
    
    scanf("%d %d %d %d", &N, &M, &S, &D);//城市的个数 高速公路的条数 出发地 目的地
    Inicialization();//初始化
    FindTheWay();
    printf("%d %d", dist[D], cost[D]);
    return 0;
}

void Inicialization(void) {
    
    
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            Dist[i][j] = Cost[i][j] = Infinite;//矩阵初始化为无限值

    int v1, v2, d, c;
    for (int i = 0; i < M; i++) {
    
    
        scanf("%d %d %d %d", &v1, &v2, &d, &c);
        Dist[v1][v2] = Dist[v2][v1] = d;//输入距离路径
        Cost[v1][v2] = Cost[v2][v1] = c;//输入花费路径
    }

    for (int i = 0; i < N; i++)
        dist[i] = cost[i] = Infinite;//矩阵初始化为无限值
}

void FindTheWay(void) {
    
    
    dist[S] = cost[S] = 0;//出发地为0
    visit[S] = 1;//出发地访问标记
    int v;
    for (int i = 0; i < N; i++)//记录出发地直达的路径
        if (!visit[i] && Dist[S][i] < Infinite) //如果没访问 且有路径
        {
    
    
            dist[i] = Dist[S][i];
            cost[i] = Cost[S][i];
        }
    while (1) {
    
    
        v = FindMinWay();//找出最短出发地直达且未访问的城市
        if (v == ERROR) break;
        visit[v] = 1;//找出城市的访问标记

        for (int i = 0; i < N; i++)//循环每个城市
            if (!visit[i] && Dist[v][i] < Infinite)//如果未访问且有路径
                if ((dist[v] + Dist[v][i] < dist[i]) ||
                    (dist[v] + Dist[v][i] == dist[i] && cost[v] + Cost[v][i] < cost[i])) {
    
    //如果从先到该城市再到另一城市距离小于直接到另一城市
                    //或者从先到该城市再到另一城市距离等于直接到另一城市,且花费少
                    dist[i] = dist[v] + Dist[v][i];//更新最短路径
                    cost[i] = cost[v] + Cost[v][i];
                }
    }
}

int FindMinWay(void) {
    
    
    int min = Infinite;
    int temp;

    for (int i = 0; i < N; i++)//循环每个城市 找出最短的路径
        if (!visit[i] && dist[i] < min) {
    
    
            min = dist[i];
            temp = i;
        }
    if (min == Infinite) return ERROR;
    return temp;
}

7-11 QQ帐户的申请与登陆

/**
 * 7-11 QQ帐户的申请与登陆
 *  哈希表  分离链接法
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/*账号与密码最大长度的定义
它们的最大长度需要比题目所给的大一位
这是因为还需要一个位置来储存'\0'来判断字符串的结尾*/
#define Max_Password_Len 17
#define Max_Account_Len 11
#define MaxTableSize 1000000

/*各种状态的定义
最好用正数表示成功的状态
用负数或0表示失败的状态
这样会让强迫症看了舒服一点*/
#define ERROR_WrongPW   -2
#define ERROR_Exist     -1
#define ERROR_NOTExist  0
#define New_OK          1
#define Login_OK        2

typedef char AccountType[Max_Account_Len];//账号类型定义
typedef char PasswordType[Max_Password_Len];//密码类型定义
typedef int Index;
typedef enum {
    
    
    New, Log
} Pattern;//两种模式,新建账号与登入账号

typedef struct {
    
    
    AccountType Account;
    PasswordType Password;
} ElemType;//数据类型的定义,每个对应一个用户,内含用户的账号和密码

//链表指针的定义
typedef struct LNode *PtrToLNode;
//链表结点的定义
typedef struct LNode {
    
    
    PtrToLNode Next;
    ElemType Data;
} LNode;
typedef PtrToLNode List;//链表的定义
typedef PtrToLNode Position;//哈希表中结点位置的定义

//哈希表的定义
typedef struct TblNode *HashTable;
typedef struct TblNode {
    
    
    int TableSize;//哈希表的大小
    List Heads;//储存各个列表头节点的数组
} TblNode;

int NextPrime(int N)//返回N的下一个素数
{
    
    
    int i, P;
    P = N % 2 ? N + 2 : N + 1;
    //P为N之后的第一个奇数
    while (P < MaxTableSize) {
    
    
        for (i = (int) sqrt(P); i > 2; i--)//因为只考虑奇数,所以i为2时就结束了
            if (P % i == 0)
                break;
        if (i == 2)
            break;//i为2说明P为素数
        else
            P += 2;//i!=2说明P不是素数,则P指向下一个奇数
    }
    return P;
}

int Hash(int Key, int TableSize) {
    
    //返回Key值相对应的哈希值,即其在哈希表中的储存下标
    return Key % TableSize;
}

HashTable CreateTable(int TableSize) {
    
        //构造空的哈希表
    HashTable H;
    int i;
    H = (HashTable) malloc(sizeof(TblNode));
    H->TableSize = NextPrime(TableSize);
    H->Heads = (List) malloc(sizeof(LNode) * H->TableSize);
    for (i = 0; i < H->TableSize; i++) {
    
    
        H->Heads[i].Data.Account[0] = '\0';
        H->Heads[i].Data.Password[0] = '\0';
        H->Heads[i].Next = NULL;
    }
    return H;
}

Position Find(HashTable H, ElemType Key) {
    
    
    Position Pos;
    Index p;
    if (strlen(Key.Account) > 5) //账号大于5位时取最后5位
        p = Hash(atoi(Key.Account +
                      strlen(Key.Account) - 5), H->TableSize);
    else//账号不大于5位则等于它本身
        p = Hash(atoi(Key.Account), H->TableSize);
    Pos = H->Heads[p].Next;
    while (Pos && strcmp(Key.Account, Pos->Data.Account))
        Pos = Pos->Next;
    return Pos;//Pos指向用户数据的位置,没有注册就返回NULL
}

int NewOrLog(HashTable H, ElemType Key, Pattern P) {
    
        //返回状态参数
    Position Pos, NewPos;
    Index p;
    Pos = Find(H, Key);
    switch (P) {
    
    
        case Log:
            if (Pos == NULL)
                return ERROR_NOTExist;//登陆时不存在账号
            else if (strcmp(Pos->Data.Password, Key.Password) ||
                     (strlen(Key.Password) > 16 || strlen(Key.Password) < 6))
                return ERROR_WrongPW; //密码错误或格式错误
            else
                return Login_OK;//账号和密码均正确,可以登录
        case New:
            if (Pos != NULL)
                return ERROR_Exist; //新建账号时发现已经存在这样的账号了
            else {
    
    
                NewPos = (Position) malloc(sizeof(LNode));
                strcpy(NewPos->Data.Account, Key.Account);
                strcpy(NewPos->Data.Password, Key.Password);
                if (strlen(Key.Account) > 5)
                    p = Hash(atoi(Key.Account +
                                  strlen(Key.Account) - 5), H->TableSize);
                else
                    p = Hash(atoi(Key.Account), H->TableSize);
                NewPos->Next = H->Heads[p].Next;
                H->Heads[p].Next = NewPos;
                return New_OK; //插入新值并返回插入成功
            }
    }
}

void DestroyTable(HashTable H) {
    
        //销毁哈希表
    PtrToLNode p, q;
    int i;
    for (i = 0; i < H->TableSize; i++) {
    
    
        q = H->Heads[i].Next;
        while (q) {
    
    
            p = q->Next;
            free(q);
            q = p;
        }
    }
    free(H);
}

int main(void) {
    
    
    int N, i;
    ElemType Key;
    char Input;
    Pattern P;
    HashTable H;
    scanf("%d", &N);
    H = CreateTable(2 * N);
    for (i = 0; i < N; i++) {
    
    
        scanf("\n%c %s %s", &Input, Key.Account, Key.Password);
        P = (Input == 'L') ? Log : New;
        switch (NewOrLog(H, Key, P)) {
    
    //最后根据不同返回值输出对应状态即可
            case ERROR_Exist:
                printf("ERROR: Exist\n");
                break;
            case ERROR_NOTExist:
                printf("ERROR: Not Exist\n");
                break;
            case ERROR_WrongPW:
                printf("ERROR: Wrong PW\n");
                break;
            case Login_OK:
                printf("Login: OK\n");
                break;
            case New_OK:
                printf("New: OK\n");
                break;
        }
    }
    DestroyTable(H);
    return 0;
}

7-12 人以群分

/**
 * 7-12 人以群分
 *  排序
 */

#include <stdio.h>
#include <stdlib.h>

int comfunc(const void *elem1, const void *elem2);

void sort_character(int *p, int n);

int main() {
    
    
    int n, i;
    int a[100001];

    scanf("%d", &n);
    for (i = 0; i < n; i++)
        scanf("%d", &a[i]);
    qsort(a, n, sizeof(int), comfunc);
    sort_character(a, n);

    return 0;
}

int comfunc(const void *elem1, const void *elem2) {
    
    
    int *p1 = (int *) elem1;
    int *p2 = (int *) elem2;

    return *p1 - *p2;
}

void sort_character(int *p, int n) {
    
    
    int i, j, n1, n2, sum1, sum2, dif, dif1, dif2;

    sum1 = sum2 = 0;
    dif = dif1 = dif2 = 0;
    if (n % 2 == 0) {
    
    
        n1 = n2 = n / 2;
        for (i = 0; i < n1; i++)
            sum1 += p[i];
        for (i = n1; i < n; i++)
            sum2 += p[i];
        dif = abs(sum2 - sum1);
    } else {
    
    
        n1 = n2 = n / 2;
        for (i = 0; i < n1; i++)
            sum1 += p[i];
        for (i = n / 2 + 1; i < n; i++)
            sum2 += p[i];
        dif1 = abs(sum1 + p[n1] - sum2);
        dif2 = abs(sum2 + p[n2] - sum1);
        dif = (dif1 > dif2) ? dif1 : dif2;
        if (dif1 > dif2)
            n1++;
        else
            n2++;
    }
    printf("Outgoing #: %d\n", n2);
    printf("Introverted #: %d\n", n1);
    printf("Diff = %d\n", dif);

}

7-13 寻找大富翁

/**
 * 7-13 寻找大富翁
 *  堆排序和选择排序
 */

#include <stdio.h>   //堆排序;  注意:此算法中,下标从1开始

#define max 1000010
int num[max];

void sift(int *num, int low, int high)  //将下标为low位置上的点调到适当位置
{
    
    
    int i, j, temp;
    i = low;
    j = 2 * i;   //num[j]是num[i]的左孩子结点;
    temp = num[i];  //待调整的结点
    while (j <= high) {
    
    
        if (j < high && num[j] < num[j + 1])   //如果右孩子比较大,则把j指向右孩子,j变为2*i+1;
            ++j;
        if (temp < num[j]) {
    
    
            num[i] = num[j];    //将num[j]调整到双亲结点的位置上;
            i = j;   //修改i和j的值,以便继续向下调整;
            j = i * 2;
        } else break;     //调整结束;
    }
    num[i] = temp;   //被调整的结点放入最终位置
}

int main() {
    
    
    int n, m, i, temp, count = 0;
    scanf("%d%d", &n, &m);
    for (i = 1; i <= n; i++)
        scanf("%d", &num[i]);
    if (n < m) m = n;   //注意,有一个测试点是n小于m的情况,这时,只用排前n个;
    for (i = n / 2; i >= 1; i--)  //所有结点建立初始堆
        sift(num, i, n);
    for (i = n; i >= 2; i--)   //进行n-1次循环,完成堆排序
    {
    
    
        /*以下3句换出了根节点中的关键字,将其放入最终位置*/
        temp = num[1];
        num[1] = num[i];
        num[i] = temp;
        count++;
        if (count == 1)
            printf("%d", num[i]);
        else
            printf(" %d", num[i]);
        if (count == m) break;  //打印前m个;
        sift(num, 1, i - 1);    //减少了1个关键字的无序序列,继续调整。
    }
    if (m == n) printf(" %d", num[1]);  //当n<m的特殊情况下,上面只打印了n~2,还有最后一个下标为1的没有打印,故再打印一个。
    return 0;
}

7-14 PAT排名汇总

/**
 * 7-14 PAT排名汇总
 *  快速排序
 */
#include <stdio.h>
#include <string.h>

struct stu {
    
    
    char id[14];                //考号
    int score;                  //分数
    int kc;                     //考场
};
struct stu a[30000];

int bigger(const char *s1, const char *s2) {
    
    
    for (int i = 0; i < 13; i++)
        if (s1[i] > s2[i])
            return 1;
        else if (s1[i] < s2[i])
            return 0;
    return 1;
}

void qsort(int l, int r) {
    
    
    if (l >= r)
        return;

    int i = l;
    int j = r;

    struct stu t = a[l];
    while (i != j) {
    
    
        while (i < j && (a[j].score < t.score || a[j].score == t.score && bigger(a[j].id, t.id)))
            j--;
        while (i < j && (a[i].score > t.score || a[i].score == t.score && bigger(t.id, a[i].id)))
            i++;
        if (i < j) {
    
    
            struct stu s = a[i];
            a[i] = a[j];
            a[j] = s;
        }
    }
    a[l] = a[i];
    a[i] = t;

    qsort(l, i - 1);
    qsort(i + 1, r);

    return;
}

void Copy(int *b2, int *b1, int n) {
    
    
    for (int i = 1; i <= n; i++)
        b2[i] = b1[i];
}

int main() {
    
    
    int n, j, i, top = 0;
    scanf("%d", &n);
    for (i = 1; i <= n; i++) {
    
    
        int k;
        scanf("%d", &k);
        for (j = 0; j < k; j++) {
    
    
            char id[14];
            int score;
            scanf("%s %d", id, &score);
            a[top].score = score;
            a[top].kc = i;
            strcpy(a[top].id, id);
            top++;
        }
    }
    qsort(0, top - 1);

    int levall = 1, b1[n + 1], b2[n + 1], score = a[0].score;

    for (i = 1; i <= n; i++)
        b1[i] = 1, b2[i] = 1;
    printf("%d\n", top);
    printf("%s %d %d %d\n", a[0].id, 1, a[0].kc, 1);
    int llevall = 1;            //上一个总排名
    levall = 2;                   //总排名

    Copy(b2, b1, n);
    b1[a[0].kc]++;
    for (i = 1; i < top; i++) {
    
    
        if (a[i].score == a[i - 1].score) {
    
    
            printf("%s %d %d %d\n", a[i].id, llevall, a[i].kc, b2[a[i].kc]);
            levall++;
            b1[a[i].kc]++;
        } else {
    
    
            printf("%s %d %d %d\n", a[i].id, levall, a[i].kc, b1[a[i].kc]);
            llevall = levall;
            levall++;

            Copy(b2, b1, n);
            b1[a[i].kc]++;                    //考场的排名
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_61228493/article/details/131109590