我的代码总结

1 双指针法遍历单链表,找中间结点、找倒数第k个结点

大家可以在自己电脑上新建一个 C++ 项目,并把这段代码复制到 main 函数前边,然后在你的 main 函数里调用 test_LinkList() 这个函数。

提示:用电脑网页版看,体验更好一些



// 个人微博:@王道咸鱼学长-计算机考研
// 这段代码实现了单链表的查找:双指针法(较常用)
 
#ifndef CODE_LINKLIST_H
#define CODE_LINKLIST_H
 
#include <stdio.h>
#include <stdlib.h>
 
//定义单链表结点
typedef struct LNode{        //定义单链表结点类型
    int data;           //每个节点存放一个数据元素
    struct LNode *next;          //指针指向下一个节点
}LNode, *LinkList;
 
//初始化一个单链表(带头结点)
bool InitList(LinkList &L) {
    L = (LNode *) malloc(sizeof(LNode));   //分配一个头结点
    if (L==NULL)            //内存不足,分配失败
        return false;
    L->next = NULL;         //头结点之后暂时还没有节点
    return true;
}
 
//输出链表相关的所有信息(带头结点)
void PrintList(LinkList L){
    LNode *p = L->next; //指向第1个结点
    int len = 0;        //统计链表的长度
    printf("L:头结点 —> ");
    while (p!=NULL){
        len++;          //单链表统计长度+1
        printf("%d -> ", p->data);
        p = p->next;
    }
    printf("NULL\n链表长度 = %d\n", len);
}
 
//双指针法,通过一次遍历找到中间结点
LNode * findMidNode(LinkList head){
    LNode * p=head;     //p指针,每次往后走一步
    LNode * q=head;     //q指针,每次往后走两步,当q指向最后一个结点时,p刚好指向中间那个结点
    while(q->next!=NULL){
        q = q->next;        //q往后走一步
        if (q->next!=NULL)
            q = q->next;    //q再往后走一步
        p=p->next;   //p往后走一步
    }
 
    if(p==head)
        printf("一个空链表,让我找中间结点?你一定是在逗我~");
    else
        printf("中间结点的值为:%d\n", p->data);
    return p;   //返回p所指向的结点
}
 
//双指针法,通过一次遍历找到倒数第k的结点
LNode * findDaoShuKNode(LinkList head, int k){
    LNode * p=head;     //p指针,等q指针走到第k个结点时,p指针再出发
    LNode * q=head;     //q指针,每次往前走一步
 
    int count=0;
    bool chong = false;      //p指针要不要冲?
    while(q->next!=NULL){
        q = q->next;        //q往后走一步
        count++;            //计数+1
        if (count==k)
            chong = true;   //q走到第k个结点时,p指针开冲
 
        if(chong)
            p = p->next;
    }
 
    if(p==head)
        printf("这个链表长度小于%d,并不存在倒数第k个结点\n", k);
    else
        printf("倒数第%d个结点的值为:%d\n", k, p->data);
    return p;   //返回p所指向的结点
}
 
#define N 20
//【测试代码】:建立一个单链表,并尝试用双指针法找中间结点、倒数第K个结点
void test_LinkList() {
    LinkList head;      //声明一个单链表
    InitList(head);     //初始化,新建一个头结点
    //插入一些测试数据,从1~N
    LNode * p = head;
    for (int i=1; i<=N; i++){
        p->next = (LNode *) malloc(sizeof(LNode));
        p = p->next;
        p->data = i;
        p->next = NULL;
    }
    PrintList(head);    //打印出来看一眼
 
    findMidNode(head);
 
    findDaoShuKNode(head, 3);
}
 
 
 
#endif //CODE_LINKLIST_H

2 二叉排序树的建立、插入、删除、查找

 大家可以在自己电脑上新建一个 C++ 项目,并把这段代码复制到 main 函数前边,然后在你的 main 函数里调用 test_BinarySearchTree() 这个函数。

提示:用电脑网页版看,体验更好一些



// 个人微博:@王道咸鱼学长-计算机考研

// 这段代码实现了二叉查找树BST 的 插入、删除、查找,前中后序遍历、层序遍历;求树的深度

// 同时,printBST 函数也可以利用层序遍历在你的终端打印二叉树的样子

 

#ifndef CODE_BINARYSEARCHTREE_H

#define CODE_BINARYSEARCHTREE_H

 

#include "stdio.h"

#include "stdlib.h"

 

//二叉排序树结点

typedef struct BSTNode{

    int key;                      //数据域

    struct BSTNode *lchild,*rchild;   //左、右孩子指针

}BSTNode,*BSTree;

 

//平衡二叉树结点

typedef struct AVLNode{

    int key;      //数据域

    int balance;    //平衡因子

    struct AVLNode *lchild,*rchild;

}AVLNode,*AVLTree;

 

//访问结点p

void visit(BSTNode * p){

    printf("%d,", p->key);

}

 

//先序遍历

void PreOrder(BSTree T){

    if(T!=NULL){

        visit(T);              //访问根结点

        PreOrder(T->lchild);      //递归遍历左子树

        PreOrder(T->rchild);      //递归遍历右子树

    }

}

 

//中序遍历

void InOrder(BSTree T){

    if(T!=NULL){

        InOrder(T->lchild);       //递归遍历左子树

        visit(T);           //访问根结点

        InOrder(T->rchild);       //递归遍历右子树

    }

}

 

//后序遍历

void PostOrder(BSTree T){

    if(T!=NULL){

        PostOrder(T->lchild);  //递归遍历左子树

        PostOrder(T->rchild);  //递归遍历右子树

        visit(T);           //访问根结点

    }

}

 

//求树的深度

int treeDepth(BSTree T){

    if (T == NULL) {

        return 0;

    }

    else {

        int l = treeDepth(T->lchild);

        int r = treeDepth(T->rchild);

        //树的深度=Max(左子树深度,右子树深度)+1

        return l>r ? l+1 : r+1;

    }

}

 

//在树T中找到结点p的父节点

BSTNode * findFather(BSTree T, BSTNode * p) {

    //检查T是否是p的父节点

    if (T==NULL)

        return NULL;

    if (T->lchild==p || T->rchild==p)

        return T;

 

    //在左子树找p的父节点

    BSTNode * l = findFather(T->lchild, p);

    if (l != NULL)

        return l;

 

    //在右子树找p的父节点

    BSTNode * r = findFather(T->rchild, p);

    if (r != NULL)

        return r;

 

    //左右子树中都没找到父节点。或者,根节点也没有父节点

    return NULL;

}

 

//在二叉排序树中查找值为 key 的结点(非递归实现)

BSTNode *BST_Search(BSTree T,int key){

    while(T!=NULL&&key!=T->key){   //若树空或等于根结点值,则结束循环

        if(key<T->key) T=T->lchild;    //小于,则在左子树上查找

        else  T=T->rchild;              //大于,则在右子树上查找

    }

    return T;

}

 

//在二叉排序树中查找值为 key 的结点(递归实现)

BSTNode *BSTSearch(BSTree T,int key){

    if (T==NULL)

        return NULL;    //查找失败

    if (key==T->key)

        return T;       //查找成功

    else if (key < T->key)

        return BSTSearch(T->lchild, key);   //在左子树中找

    else

        return BSTSearch(T->rchild, key);   //在右子树中找

}

 

 

//在二叉排序树插入关键字为k的新结点(递归实现)

int BST_Insert(BSTree &T, int k){

    if(T==NULL){            //原树为空,新插入的结点为根结点

        T=(BSTree)malloc(sizeof(BSTNode));

        T->key=k;

        T->lchild=T->rchild=NULL;

        return  1;          //返回1,插入成功

    }

    else if(k==T->key)       //树中存在相同关键字的结点,插入失败

        return  0;

    else if(k<T->key)        //插入到T的左子树

        return  BST_Insert(T->lchild,k);

    else                  //插入到T的右子树

        return  BST_Insert(T->rchild,k);

}

 

//在二叉排序树 T 中删除结点 p(不考虑p为根节点的情况)

int BST_DeleteNode(BSTree &T, BSTNode * p){

    if (p==NULL)

        return 0;

 

    //先找到 p 的父节点 father

    BSTNode *f = findFather(T, p);

    //判断 p 是 f 的左孩子 还是 右孩子

    bool isLchild = false;      //isLchild == false 表示 p 是右孩子

    if (f->lchild == p)

        isLchild = true;        //isLchild == true 表示 p 是左孩子

 

    // p 是叶子,直接删除,同时要修改其父节点的指针

    if (p->lchild==NULL && p->rchild==NULL) {

        if (isLchild){          //p是f的左孩子

            f->lchild = NULL;   //父节点f的左指针指向NULL

        } else {                //p是f的右孩子

            f->rchild = NULL;   //父节点f的右指针指向NULL

        }

        free(p);                //释放结点 p

        return 1;               //删除成功,返回1

    }

 

    // p 只有左子树,则让左子树顶替p即可

    if (p->lchild!=NULL && p->rchild==NULL) {

        if (isLchild){              //p是f的左孩子

            f->lchild = p->lchild;  //父节点f的左指针指向p的左子树

        } else {                    //p是f的右孩子

            f->rchild = p->lchild;  //父节点f的右指针指向p的左子树

        }

        free(p);                //释放结点 p

        return 1;               //删除成功,返回1

    }

 

    // p 只有右子树,则让右子树顶替p即可

    if (p->lchild==NULL && p->rchild!=NULL) {

        if (isLchild){              //p是f的左孩子

            f->lchild = p->rchild;  //父节点f的左指针指向p的右子树

        } else {                    //p是f的右孩子

            f->rchild = p->rchild;  //父节点f的右指针指向p的右子树

        }

        free(p);                //释放结点 p

        return 1;               //删除成功,返回1

    }

 

    //上面几种条件都不满足,说明 p 既有左子树,也有右子树。此时,可让p的后继来顶替p,然后删除其后继结点

    BSTNode * q = p->rchild;

    //找到 p的右子树中,最左下角的一个结点,这个结点就是p的后继

    while(q->lchild!=NULL){

        q = q->lchild;

    }

    p->key = q->key;            //用后继结点的关键字顶替被删除节点

    BST_DeleteNode(T, q);       //转化为删除节点q的操作

    return 1;

}

 

//从二叉排序树 T 中删除关键字为 k 的结点

int BST_DeleteKey(BSTree &T, int k){

    BSTNode * p = BST_Search(T, k);

    if (p==NULL){

        printf("【删除失败】,不存在这个关键字 %d\n", k);

        return  0;          //返回0,删除失败

    }

    if (p==T){

        printf("【删除失败】,关键字 %d 是根节点。答应我,我们不删除根节点,好吗?\n(注:删除根节点会更麻烦一点,有能力的同学可以自己动手实现)", k);

        return  0;          //返回0,删除失败

    }

    BST_DeleteNode(T, p);   //删除节点p

 

    printf("【删除成功】,关键字为 %d\n", k);

}

 

//按照 str[] 中的关键字序列建立二叉排序树

void Creat_BST(BSTree &T,int str[],int n){

    T=NULL;          //初始时T为空树

    int i=0;

    while(i<n){       //依次将每个关键字插入到二叉排序树中

        BST_Insert(T,str[i]);

        i++;

    }

}

 

 

//链式队列结点,用于辅助实现层序遍历

typedef struct LinkNode{

    BSTNode * data;

    struct LinkNode *next;

}LinkNode;

 

typedef struct{

    LinkNode *front,*rear; //队头队尾

}LinkQueue;

 

//初始化队列(带头结点)

void InitQueue(LinkQueue &Q){

    //初始时 front、rear 都指向头结点

    Q.front=Q.rear=(LinkNode*)malloc(sizeof(LinkNode));

    Q.front->next=NULL;

}

 

//判断队列是否为空(带头结点)

bool IsEmpty(LinkQueue Q){

    if(Q.front==Q.rear)

        return true;

    else

        return false;

}

 

//新元素入队(带头结点)

void EnQueue(LinkQueue &Q,BSTNode * x){

    LinkNode *s=(LinkNode *)malloc(sizeof(LinkNode));

    s->data=x;

    s->next=NULL;

    Q.rear->next=s;    //新结点插到表尾之后

    Q.rear=s;          //修改表尾指针

}

 

//队头元素出队(带头结点)

bool DeQueue(LinkQueue &Q,BSTNode * &x){

    if(Q.front==Q.rear)

        return false;           //空队

    LinkNode *p=Q.front->next;  //p指向此次出队的结点

    x=p->data;                  //用变量x返回队头元素

    Q.front->next=p->next;      //修改头结点的 next 指针

    if(Q.rear==p)               //此次是最后一个结点出队

        Q.rear=Q.front;         //修改 rear 指针

    free(p);                    //释放结点空间

    return true;

}

 

//层序遍历

void LevelOrder(BSTree T){

    LinkQueue Q;

    InitQueue(Q);              //初始化辅助队列

    BSTree p;

    EnQueue(Q,T);              //将根结点入队

 

    while(!IsEmpty(Q)){             //队列不空则循环

        DeQueue(Q, p);          //队头结点出队

        visit(p);               //访问队头元素

        if(p->lchild!=NULL)

            EnQueue(Q,p->lchild);  //左孩子入队

        if(p->rchild!=NULL)

            EnQueue(Q,p->rchild);  //右孩子入队

    }

}

 

 

//基于层序遍历打印出树的样子

void printBST(BSTree T){

    LinkQueue Q;

    InitQueue(Q);              //初始化辅助队列

    BSTree p;

    EnQueue(Q,T);              //将根结点入队

 

    //打印h层二叉树

    int h=treeDepth(T);

    int maxLayer = pow(2, h-1); //最下边一层有几个结点

    printf("\n树的亚子:\n");

 

    for (int i=1; i<=h; i++){

        int sum = pow(2, i-1);  //本层的结点数

        int gap = maxLayer/sum;     //本层各节点之间的间隔距离

        for (int j=0; j<gap/2; j++)

            printf("\t");

        //打印本层结点

        for (int j=0; j<sum; j++){

            DeQueue(Q, p);          //队头结点出队

            if (p==NULL){

                printf("空");

            }else{

                printf("%d", p->key);      //打印结点的值

            }

 

            //放入下一级的孩子

            if (p==NULL){

                EnQueue(Q,NULL);   //占两个位置

                EnQueue(Q,NULL);   //占两个位置

            } else {

                EnQueue(Q,p->lchild);  //左孩子入队

                EnQueue(Q,p->rchild);  //右孩子入队

            }

 

            for (int k=0; k<gap; k++)

                printf("\t");

        }

 

        printf("\n");

    }

}

 

//【测试代码】:测试二叉排序树的创建、遍历、求深度、插入、查找、删除 操作

int test_BinarySearchTree() {

    int str[] = {985,211,996,45,12,24};

    BSTree root;                //定义一颗空的而叉查找树

    Creat_BST(root, str, 6);    //按照 str[] 数组的顺序依次往二叉查找树中插入元素,其中 6 是数组的长度,大家可自行更改

 

    printf("\n中序遍历:");

    InOrder(root);

 

    printf("\n先序遍历:");

    PreOrder(root);

 

    printf("\n后序遍历:");

    PostOrder(root);

 

    printf("\n层序遍历:");

    LevelOrder(root);

 

    printf("\n树的深度=%d", treeDepth(root));

 

    printBST(root);         //打印出树的样子

 

    //下面这段代码,用于测试插入操作

    BST_Insert(root, 666);  //往二叉排序树插入关键字666

    printBST(root);         //打印出树的样子

    BST_Insert(root, 1000);  //往二叉排序树插入关键字1000

    printBST(root);         //打印出树的样子

 

    //下面这段代码,用于测试查找操作(非递归实现)

    int key1 = 2333;

    BSTNode * result1;   //用于保存查找结果

    result1 = BST_Search(root, key1);      //在排序树中查找关键字 666

    if (result1!=NULL)

        printf("关键字%d查找成功(非递归实现)\n", key1);

    else

        printf("关键字%d查找失败(非递归实现)\n", key1);

 

 

    //下面这段代码,用于测试查找操作(非递归实现)

    int key2 = 996;

    BSTNode * result2;   //用于保存查找结果

    result2 = BST_Search(root, key2);      //在排序树中查找关键字 666

    if (result2!=NULL)

        printf("关键字%d查找成功(递归实现)\n", key2);

    else

        printf("关键字%d查找失败(递归实现)\n", key2);

 

 

    //下面这段代码,用于测试二叉排序树的删除操作。同学们可以自己更改要删除的关键字

    BST_DeleteKey(root, 211);

    printBST(root);         //删除之后打印出树的样子

 

    return 0;

}

3 顺序存储的二叉树、链式存储的二叉树 相关的各种代码

这段代码有点多,定义了顺序存储的二叉树、链式存储的二叉树。大家可以把这段代码复制到你的 main 函数之前,并在 main 函数中调用以下几个函数来观察效果。



调用 test_SqBiTree() 函数,这个函数中写了一个例子:建立一棵顺序二叉树,并基于顺序存储的二叉树,进行先序、中序、后序遍历

调用 test_CreateBySqBiTree() 函数,这个函数中写了一个例子:根据顺序存储的二叉树,构建了一棵等价的链式存储二叉树

调用 test_CreateByBiTree() 函数,这个函数中写了一个例子:根据链式存储的二叉树,构建了一棵等价的顺序存储二叉树

调用 test_BiTreeWidth() 函数,这个函数中写了一个例子:建立一棵链式存储的二叉树,并求它的宽度(对应结课考试的算法题第二题)

调用 test_IsCompleteBinaryTree() 函数,这个函数中写了一个例子:建立二叉树,并用层序遍历的思想,判断该二叉树是否为完全二叉树



提示:用电脑网页版看,体验更好一些



// 个人微博:@王道咸鱼学长-计算机考研
 
#ifndef BITREEWIDTH_H
#define BITREEWIDTH_H
 
#include "stdio.h"
#include "stdlib.h"
 
/*~~~~~~~~~~~~~分~~~~~~~~~~~~~~~~~~~~隔~~~~~~~~~~~~~~~~~~~线~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// 下面这段代码实现的二叉树的顺序存储,以及基于顺序存储的二叉树如何找左/右孩子、如何找父节点,如何基于顺序二叉树实现前中后序遍历
// 建议同学们从 test_SqBiTree() 函数开始阅读代码
 
typedef struct TreeNode {
    int data;       //结点中的数据元素
    bool isEmpty;   //结点是否为空
} TreeNode;
 
 
//初始化顺序存储的二叉树,所有结点标记为"空"
void InitSqBiTree (TreeNode t[], int length) {
    for (int i=0; i<length; i++){
        t[i].isEmpty=true;
    }
}
 
//判断下标为 index 的结点是否为空
bool isEmpty(TreeNode t[], int length, int index){
    if (index >= length || index < 1) return true;   //下标超出合法范围
    return t[index].isEmpty;
}
 
//访问一个结点,你可以在这里做任何你想做的事
void visitNode(TreeNode node){
    printf("%d ", node.data);
}
 
//找到下标为 index 的结点的左孩子,并返回左孩子的下标,如果没有左孩子,则返回 -1
int getLchild(TreeNode t[], int length, int index){
    int lChild = index * 2;                     //如果左孩子存在,则左孩子的下标一定是 index * 2
    if (isEmpty(t, length, lChild)) return -1;  //左孩子为空
    return lChild;
}
 
//找到下标为 index 的结点的右孩子,并返回右孩子的下标,如果没有右孩子,则返回 -1
int getRchild(TreeNode t[], int length, int index){
    int rChild = index * 2 + 1;                 //如果右孩子存在,则右孩子的下标一定是 index * 2 + 1
    if (isEmpty(t, length, rChild)) return -1;  //右孩子为空
    return rChild;
}
 
//找到下标为 index 的结点的父节点,并返回父节点的下标,如果没有父节点,则返回 -1
int getFather(TreeNode t[], int length, int index){
    if (index == 1) return -1;          //根节点没有父节点
    int father = index / 2;             //如果父节点存在,则父节点的下标一定是 index/2,整数除法会自动向下取整
    if (isEmpty(t, length, father)) return -1;
    return father;
}
 
 
//从下标为 index 的结点开始先序遍历
void PreOrderSqTree (TreeNode *t, int length, int index){
    if (isEmpty(t, length, index))    //当前为空节点
        return;
    visitNode(t[index]);     //访问结点
    PreOrderSqTree(t, length, getLchild(t, length, index));       //先序遍历左子树
    PreOrderSqTree(t, length, getRchild(t, length, index));       //先序遍历右子树
}
 
//从下标为 index 的结点开始中序遍历
void InOrderSqTree (TreeNode *t, int length, int index){
    if (isEmpty(t, length, index))    //当前为空节点
        return;
    InOrderSqTree(t, length, getLchild(t, length, index));       //中序遍历左子树
    visitNode(t[index]);     //访问结点
    InOrderSqTree(t, length, getRchild(t, length, index));       //中序遍历右子树
}
 
//从下标为 index 的结点开始后序遍历
void PostOrderSqTree (TreeNode *t, int length, int index){
    if (isEmpty(t, length, index))    //当前为空节点
        return;
    PostOrderSqTree(t, length, getLchild(t, length, index));       //后序遍历左子树
    PostOrderSqTree(t, length, getRchild(t, length, index));       //后序遍历右子树
    visitNode(t[index]);     //访问结点
}
 
//【测试代码】:建立一棵顺序二叉树,并基于顺序结构实现先序、中序、后序遍历
int test_SqBiTree() {
    TreeNode t[100];        //定义一棵顺序存储的二叉树
    InitSqBiTree(t, 100);   //初始化为空树
    //往顺序二叉树插入一些原始数据,用t[1]作为根节点,t[0]不会用于存储任何东西
    for (int i=1; i<=12; i++){
        t[i].data = i;              //插入12个结点(就是王道数据结构考点精讲视频 5.2.3 的第一个例子,大家可以看看课件)
        t[i].isEmpty = false;       //插入结点后标记为非空
    }
 
    printf("【对顺序存储的二叉树先序遍历】:");
    PreOrderSqTree(t, 100, 1);    //从根节点开始先序遍历
    printf("\n");
 
    printf("【对顺序存储的二叉树中序遍历】:");
    InOrderSqTree(t, 100, 1);     //从根节点开始中序遍历
    printf("\n");
 
    printf("【对顺序存储的二叉树后序遍历】:");
    PostOrderSqTree(t, 100, 1);   //从根节点开始后序遍历
    printf("\n");
    return 0;
}
 
/*~~~~~~~~~~~~~分~~~~~~~~~~~~~~~~~~~~隔~~~~~~~~~~~~~~~~~~~线~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
// 从这个分割线开始,下面这些代码实现了链式存储的二叉树
// 其中,treeWidth 函数实现了"求二叉树的宽度",也就是 "2021数据结构强化课考试"算法题第二题的参考答案
// 这段代码实现了建立一棵二叉树、并求二叉树的宽度
 
 
//二叉树的结点(链式存储)
typedef struct BiTNode{
    int data;                     //数据域
    struct BiTNode *lchild,*rchild;   //左、右孩子指针
}BiTNode,*BiTree;
 
BiTNode * test;
 
//访问二叉树的结点 p
void visit(BiTNode * p){
    if (p==NULL)
        return;
    printf("%d ", p->data);
}
 
//先序遍历二叉树
void PreOrder (BiTree root){
    if (root==NULL)
        return;
    visit(root);    //访问根节点
    PreOrder(root->lchild);
    PreOrder(root->rchild);
}
 
//中序遍历二叉树
void InOrder (BiTree root){
    if (root==NULL)
        return;
    InOrder(root->lchild);
    visit(root);    //访问根节点
    InOrder(root->rchild);
}
 
//后序遍历二叉树
void PostOrder (BiTree root){
    if (root==NULL)
        return;
    PostOrder(root->lchild);
    PostOrder(root->rchild);
    visit(root);    //访问根节点
}
 
//链式队列结点,用于辅助实现层序遍历(408考试中,对树层序遍历不需要自己定义队列,直接使用队列的基本操作并加以说明即可)
typedef struct QNode{
    BiTNode * data;
    struct QNode *next;
} QNode;
 
typedef struct{
    QNode *front,*rear; //队头队尾
}Queue;
 
//初始化队列(队列带头结点)
void InitQueue(Queue &Q){
    //初始时 front、rear 都指向头结点
    Q.front=Q.rear=(QNode*)malloc(sizeof(QNode));
    Q.front->next=NULL;
}
 
//判断队列是否为空(队列带头结点)
bool IsEmpty(Queue Q){
    if(Q.front==Q.rear)
        return true;
    else
        return false;
}
 
//新元素入队(队列带头结点)
void EnQueue(Queue &Q, BiTNode * x){
    QNode *s=(QNode *)malloc(sizeof(QNode));
    s->data=x;
    s->next=NULL;
    Q.rear->next=s;    //新结点插到表尾之后
    Q.rear=s;          //修改表尾指针
}
 
//队头元素出队(队列带头结点)
bool DeQueue(Queue &Q, BiTNode * &x){
    if(Q.front==Q.rear)
        return false;           //空队
    QNode *p=Q.front->next;  //p指向此次出队的结点
    x=p->data;                  //用变量x返回队头元素
    Q.front->next=p->next;      //修改头结点的 next 指针
    if(Q.rear==p)               //此次是最后一个结点出队
        Q.rear=Q.front;         //修改 rear 指针
    free(p);                    //释放结点空间
    return true;
}
 
//层序遍历
void LevelOrder(BiTree T){
    Queue Q;
    InitQueue(Q);              //初始化辅助队列
    BiTree p;
    EnQueue(Q,T);              //将根结点入队
 
    while(!IsEmpty(Q)){             //队列不空则循环
        DeQueue(Q, p);          //队头结点出队
        visit(p);               //访问队头元素
        if(p->lchild!=NULL)
            EnQueue(Q,p->lchild);  //左孩子入队
        if(p->rchild!=NULL)
            EnQueue(Q,p->rchild);  //右孩子入队
    }
}
 
//基于"层序遍历"的思想,判断一棵二叉树是否是完全二叉树。
bool IsCompleteBinaryTree(BiTree T){
    if (T==NULL){
        printf("老哥,空树不是完全二叉树");
        return false;   //不是完全二叉树,返回0
    }
 
    Queue Q;
    InitQueue(Q);              //初始化辅助队列
    BiTree p;
    EnQueue(Q,T);              //将根结点入队
 
    bool flag = false;              //层序遍历时,只要出现第一个叶子,或出现第一个只有左孩子的结点,则后序所有结点都必须是叶子
    while(!IsEmpty(Q)){             //队列不空则循环
        DeQueue(Q, p);          //队头结点出队
 
        //当前结点没有左孩子,但是有右孩子的结点,则一定不是完全二叉树
        if(p->lchild==NULL && p->rchild!=NULL){
            return false;
        }
 
        //当前结点是叶子结点,则之后出现的结点必须是叶子
        if(p->lchild==NULL && p->rchild==NULL){
            flag = true;    //flag=true,表示之后必须全都是叶子
        }
 
        //当前结点有左孩子,但是没有右孩子,则之后出现的结点必须是都叶子
        if(p->lchild!=NULL && p->rchild==NULL){
            if (flag) {         //之前就出现过叶子,或之前就出现过只有一个孩子的分支节点
                return false;   //不是完全二叉树
            }
            flag = true;    //flag=true,表示之后必须全都是叶子
        }
 
        //当前结点有左孩子,也右孩子
        if(p->lchild!=NULL && p->rchild!=NULL){
            if (flag) {         //之前就出现过叶子,或之前就出现过只有一个孩子的分支节点
                return false;   //不是完全二叉树
            }
        }
 
        visit(p);
        if(p->lchild!=NULL)
            EnQueue(Q,p->lchild);  //左孩子入队
        if(p->rchild!=NULL)
            EnQueue(Q,p->rchild);  //右孩子入队
    }
}
 
//用笨方法创建一棵二叉树
BiTree creatTree(){
    BiTree root = (BiTree) malloc(sizeof(BiTNode));
    root->data=1;
 
    BiTNode * p1 = (BiTNode *)malloc(sizeof(BiTNode));
    p1->data=2;
    root->lchild=p1;
 
    BiTNode * p2 = (BiTNode *)malloc(sizeof(BiTNode));
    p2->data=3;
    root->rchild=p2;
 
    BiTNode * p3 = (BiTNode *)malloc(sizeof(BiTNode));
    p3->data=4;
    p1->lchild=p3;
    p3->lchild = NULL;
    p3->rchild = NULL;
 
    BiTNode * p4 = (BiTNode *)malloc(sizeof(BiTNode));
    p4->data=5;
    p1->rchild=p4;
 
    BiTNode * p5 = (BiTNode *)malloc(sizeof(BiTNode));
    p5->data=6;
    p2->lchild=p5;
    p5->lchild = NULL;
    p5->rchild = NULL;
 
    BiTNode * p6 = (BiTNode *)malloc(sizeof(BiTNode));
    p6->data=7;
    p2->rchild=p6;
    p6->lchild = NULL;
    p6->rchild = NULL;
 
    BiTNode * p7 = (BiTNode *)malloc(sizeof(BiTNode));
    p7->data=8;
    p4->lchild=p7;
    p7->lchild = NULL;
    p7->rchild = NULL;
 
    BiTNode * p8 = (BiTNode *)malloc(sizeof(BiTNode));
    p8->data=9;
    p4->rchild=p8;
 
    BiTNode * p9 = (BiTNode *)malloc(sizeof(BiTNode));
    p9->data=10;
    p8->lchild=p9;
    p9->lchild = NULL;
    p9->rchild = NULL;
 
    BiTNode * p10 = (BiTNode *)malloc(sizeof(BiTNode));
    p10->data=11;
    p8->rchild=p10;
    p10->lchild = NULL;
    p10->rchild = NULL;
 
    test=p3;
 
    return root;
}
 
//先序遍历,同时统计各层结点总数
void PreOrderWidth(BiTree T, int level, int *width){
    if (T == NULL)  return;
    width[level]++;     //根据当前结点所处层数,累加该层结点总数
    PreOrderWidth(T->lchild, level + 1, width);      //遍历左子树
    PreOrderWidth(T->rchild, level + 1, width);      //遍历右子树
}
 
#define H 10        //树的最大高度为10
//求树的宽度
int treeWidth (BiTree T) {
    int width[H];   //定义一个数组,用于统计各层的结点总数
    for (int i=0; i<H; i++)
        width[i]=0;
 
    PreOrderWidth(T, 0, width);   //前序遍历二叉树,同时统计各层结点总数
 
    int maxWidth = 0;       //找到最大宽度
    for (int i=0; i<H; i++){
        if(width[i]>maxWidth)
            maxWidth =width[i];
    }
    return maxWidth;        //返回树的宽度
}
 
//利用已有的顺序二叉树,构建一棵等价的链式二叉树。本质上就是对顺序存储的二叉树进行先序遍历,同时构建新结点
void CreateBySqBiTree (TreeNode t[], int length, int index, BiTree &root){
    //判断以 t[index] 为根的树是否为空
    if(isEmpty(t, length, index)){
        root = NULL;    //如果是空树,那么链式二叉树的根指针指向空即可
        return;
    }
 
    //t[index] 不是空节点,则建立与之对应的链式二叉树结点
    root = (BiTNode *) malloc(sizeof(BiTNode));
    root->data = t[index].data;
 
    int index_lChild = getLchild(t, length, index);     //找到当前结点的左孩子
    CreateBySqBiTree (t, length, index_lChild, root->lchild);   //递归构建左子树
 
    int index_rChild = getRchild(t, length, index);     //找到当前结点的右孩子
    CreateBySqBiTree (t, length, index_rChild, root->rchild);   //递归构建右子树
}
 
// 利用已有的链式二叉树,构建一棵等价的顺序二叉树。目前传入的根节点 root,应该对应数组中的 t[index]
void CreateByBiTree (TreeNode t[], int length, int index, BiTree root){
    //根节点为空
    if (root==NULL){
        return;
    }
 
    //当前遍历的这个结点在数组中对应的下标,已经越界
    if (index >= length) {
        printf("兄弟啊,你给的这个数组,存不下这么大的树\n");
        return;
    }
 
    //将结点信息更新到数组中
    t[index].isEmpty = false;
    t[index].data = root->data;
 
    //当前结点的左孩子,在数组中应该对应 t[index*2]
    CreateByBiTree(t, length, index*2, root->lchild);
 
    //当前结点的右孩子,在数组中应该对应 t[index*2+1]
    CreateByBiTree(t, length, index*2+1, root->rchild);
}
 
//【测试代码】:根据顺序存储的二叉树,构造一棵与之对应的链式二叉树
int test_CreateBySqBiTree (){
    TreeNode t[100];        //定义一棵顺序存储的二叉树
    InitSqBiTree(t, 100);   //初始化为空的顺序二叉树
    //往顺序二叉树插入一些原始数据,用t[1]作为根节点,t[0]不会用于存储任何东西
    for (int i=1; i<=12; i++){
        t[i].data = i;              //插入12个结点(就是王道数据结构考点精讲视频 5.2.3 的第一个例子,大家可以看看课件)
        t[i].isEmpty = false;       //插入结点后标记为非空
    }
 
    BiTree root;    //链式存储的二叉树
    CreateBySqBiTree(t, 100, 1, root);
 
    printf("\n【对链式存储的二叉树先序遍历】:");
    PreOrder(root);
 
    printf("\n【对链式存储的二叉树中序遍历】:");
    InOrder(root);
 
    printf("\n【对链式存储的二叉树后序遍历】:");
    PostOrder(root);
}
 
//【测试代码】:根据链式存储的二叉树,构造一棵与之对应的顺序存储二叉树
int test_CreateByBiTree (){
    TreeNode t[100];        //定义一棵顺序存储的二叉树
    InitSqBiTree(t, 100);   //初始化为空的顺序二叉树
 
    //随便创建一棵链式存储的二叉树
    BiTree root = creatTree();
 
    printf("\n【对链式存储的二叉树先序遍历】:");
    PreOrder(root);
 
    printf("\n【对链式存储的二叉树中序遍历】:");
    InOrder(root);
 
    printf("\n【对链式存储的二叉树后序遍历】:");
    PostOrder(root);
 
    printf("\n【对链式存储的二叉树层序遍历】:");
    LevelOrder(root);
 
    //构建顺序存储的二叉树,根节点应对应数组元素 t[1]
    CreateByBiTree(t, 100, 1, root);
 
    printf("\n【链式二叉树转顺序二叉树】数组的值为:");
    for (int i=1; i<100; i++){
        if (t[i].isEmpty)
            printf("空 ");
        else
            printf("%d ", t[i].data);
    }
}
 
//【测试代码】:求二叉树的宽度
int test_BiTreeWidth() {
    //随便创建一棵二叉树
    BiTree root = creatTree();
 
    //求树的宽度
    int width = treeWidth(root);
 
    printf("小伙汁,你这棵树的宽度=%d\n", width);
    return 0;
}
 
void test_IsCompleteBinaryTree(){
    //随便创建一棵二叉树
    BiTree root = creatTree();
    printf("\n【对链式存储的二叉树先序遍历】:");
    PreOrder(root);
    printf("\n【对链式存储的二叉树中序遍历】:");
    InOrder(root);
    printf("\n【对链式存储的二叉树层序遍历】:");
    LevelOrder(root);
    printf("\n【层序遍历检查是否是完全二叉树】:");
    if(IsCompleteBinaryTree(root)){
        printf("\n 这棵二叉树是完全二叉树");
    } else {
        printf("\n 这棵二叉树不是完全二叉树");
    }
 
    //再建立一棵二叉树,利用顺序二叉树生成链式二叉树
    TreeNode t[100];        //定义一棵顺序存储的二叉树
    InitSqBiTree(t, 100);   //初始化为空的顺序二叉树
    //往顺序二叉树插入一些原始数据,用t[1]作为根节点,t[0]不会用于存储任何东西
    for (int i=1; i<=15; i++){
        t[i].data = i;              //插入12个结点(就是王道数据结构考点精讲视频 5.2.3 的第一个例子,大家可以看看课件)
        t[i].isEmpty = false;       //插入结点后标记为非空
    }
    BiTree T;    //链式存储的二叉树
    CreateBySqBiTree(t, 100, 1, T);
    printf("\n【对链式存储的二叉树先序遍历】:");
    PreOrder(T);
    printf("\n【对链式存储的二叉树中序遍历】:");
    InOrder(T);
    printf("\n【对链式存储的二叉树层序遍历】:");
    LevelOrder(T);
    printf("\n【层序遍历检查是否是完全二叉树】:");
    if(IsCompleteBinaryTree(T)){
        printf("\n 这棵二叉树是完全二叉树");
    } else {
        printf("\n 这棵二叉树不是完全二叉树");
    }
}
#endif

4 实现散列表(用拉链法解决冲突)

大家可以在自己电脑上新建一个 C++ 项目,并把这段代码复制到 main 函数前边,然后在你的 main 函数里调用 test_HashTable() 这个函数。跑一跑看看效果



提示:用电脑网页版看,体验更好一些

// 个人微博:@王道咸鱼学长-计算机考研
// 这段代码实现了散列表(用拉链法解决冲突)
 
#ifndef CODE_HASHTABLE_H
#define CODE_HASHTABLE_H
 
#include "stdlib.h"
#include "stdio.h"
 
//用于存储关键字的结点
typedef struct HaNode {
    int key;
    struct HaNode * next;
} HaNode;
 
#define N 7          //散列表的长度
typedef struct {
    HaNode * h;    //链头指针
} HashTable[N];
 
/**
 * 初始化散列表
 * @param hashTable
 */
void InitHashTable (HashTable t){
    for (int i=0; i<N; i++)
        t[i].h = NULL;
}
 
/**
 * 在散列表 t 中插入元素 key
 * @param t
 * @param key
 * @return
 */
int InsertElem (HashTable t, int key){
    //申请新结点
    HaNode * p = (HaNode *)malloc(sizeof(HaNode));
    p->key = key;
 
    //头插法插入关键字key对应的拉链
    int index = key%N;
    p->next = t[index].h;
    t[index].h = p;
    return 1;       //插入成功
}
 
/**
 * 在散列表 t 中删除值为 key 的元素
 * @param t
 * @param key
 * @return
 */
int DeleteElem (HashTable t, int key){
    int index = key%N;
    int flag = 0;   //flag=0表示删除失败,flag=1表示删除成功
    HaNode * pPre = NULL;       //pPre在遍历过程中指向p的前驱结点
    HaNode * p = t[index].h;    //p指针从第一个结点开始遍历
    while (p!=NULL) {
        //找到链表中值为key的结点并删除
        if (p->key==key){
            if (pPre==NULL){    //pPre==NULL说明p结点是当前这个链表的第一个元素
                t[index].h = p->next;   //头指针指向p的下一个结点
                HaNode * s = p;
                p = p->next;
                free(s);
            } else {
                pPre->next = p->next;
                HaNode * s = p;
                p = p->next;
                free(s);
            }
            flag = 1;
        } else {
            //当前结点 p 的值不等于 key,继续检查下一个结点
            pPre = p;
            p = p->next;
        }
    }
    return flag;       //遍历整个链表,没找到关键字为key的结点,返回0表示删除失败
}
 
/**
 * 在散列表 t 中查找值为 key 的元素
 * @param t
 * @param key
 * @return
 */
HaNode * GetElem (HashTable t, int key){
    int index = key%N;
    HaNode * p = t[index].h;    //p指针从第一个结点开始遍历
    while (p!=NULL) {
        //找到链表中值为key的结点并删除
        if (p->key==key){
            return p;       //返回第一个关键字为key的结点
        }
        p = p->next;
    }
    return NULL;       //遍历整个链表,没找到关键字为key的结点,返回NULL表示查找失败
}
 
//打印出散列表的样子
void PrintHashTable(HashTable t){
    printf("你的散列表长酱紫:\n");
    for (int i=0; i<N; i++){
        printf("HashTable[%d]——>", i);
        HaNode * p = t[i].h;
        while (p!=NULL){
            printf("%d——>", p->key);
            p=p->next;
        }
        printf("NULL\n");
    }
}
 
/**
 * 测试函数,初始化散列表 h,并插入、查找、删除一些元素
 */
void test_HashTable() {
    HashTable t;    //定义一个散列表
    InitHashTable(t);   //初始化
    PrintHashTable(t);  //打印出来看一眼
 
    //测试插入操作,生成50个随机数,并插入散列表
    for (int i=0; i<50; i++){
        int key = rand()%20;   //随机数范围限制在20以内好了,不然看着有点累
        InsertElem(t, key);
    }
    PrintHashTable(t);  //打印出来看一眼
    InsertElem(t, 985); //手动插入一个关键字
    PrintHashTable(t);  //打印出来看一眼
    InsertElem(t, 211); //手动插入一个关键字
    PrintHashTable(t);  //打印出来看一眼
 
    //测试删除操作
    DeleteElem(t, 9);   //删除9
    PrintHashTable(t);  //打印出来看一眼
    DeleteElem(t, 5);   //删除5
    PrintHashTable(t);  //打印出来看一眼
 
    //测试查找操作
    HaNode * result;
    int key = 9;        //查找关键字9
    result = GetElem(t, key);
    if (result==NULL){
        printf("哎呀,没找到你的结点:%d\n", key);
    } else {
        printf("成功找到你的结点:%d\n", key);
    }
 
    key = 985;          //查找关键字985
    result = GetElem(t, key);
    if (result==NULL){
        printf("哎呀,没找到你的结点:%d\n", key);
    } else {
        printf("成功找到你的结点:%d\n", key);
    }
}

5 用单链表实现多项式加法(对应:补充算法题第一题)

大家可以在自己电脑上新建一个 C++ 项目,并把这段代码复制到 main 函数前边,然后在你的 main 函数里调用 test_PolynomialAdditation() 这个函数。跑一跑看看效果

提示:用电脑网页版看,体验更好一些

注:这段代码对应强化课“补充算法题”第一题



// 个人微博:@王道咸鱼学长-计算机考研
// 注:这段代码对应强化课“补充算法题”第一题
// 这段代码用单链表存储多项式,多项式的各个项按照指数递增的顺序存储在单链表中。另外,Addition 函数实现了两个多项式的加法
 
#ifndef CODE_POLYNOMIALADDITATION_H
#define CODE_POLYNOMIALADDITATION_H
 
#include "stdio.h"
#include "stdlib.h"
//多项式的数据结构定义
typedef struct PoNode {
    int co;   //系数,此处假设系数都为整数
    int ex;   //指数
    struct PoNode *next;    //指向下一个结点
} *Polynomial;
 
/**
 * 打印多项式p
 * @param p
 */
void printPolynomial (Polynomial p){
    printf("【多项式】:");
    if (p==NULL)
        printf("这是一个空多项式\n");
    while (p!=NULL){
        printf("%dX^%d ", p->co, p->ex);
        p = p->next;
    }
    printf("\n");
}
 
/**
 * 往多项式 p 中插入新结点,插入后任然保持按指数递增
 * @param p
 * @param co    系数
 * @param ex    指数
 * @return
 */
int InsertNode(Polynomial &p, int co, int ex){
    //malloc一个新结点
    struct PoNode * q = (struct PoNode *)malloc(sizeof(struct PoNode));
    q->ex = ex;
    q->co = co;
    q->next = NULL;
 
//    //原本是个空链表,查到链头即可
//    if (p == NULL){
//        printf("【插入成功】:%dX^%d ", q->co, q->ex);
//        return 1;               //插入成功,返回1
//    }
 
    struct PoNode * find = p;         //用指针find遍历链表
    struct PoNode * pre = NULL;       //指向find的前驱结点
 
    //多项式链表中,各节点的指数依次递增,遍历找到新结点的后继
    while (find!=NULL && find->ex < ex){
        if(find->ex == ex){
            free(q);    //释放空间
            printf("【插入失败】:原本就有相同指数的项\n");
            return 0;
        }
        pre = find;
        find=find->next;
    }
 
    q->next = find;         //新结点的next指针指向其后继
    if (pre==NULL) {
        p=q;                //新结点插入到链头
    } else {
        pre->next = q;      //新结点插入到pre之后
    }
    printf("【插入成功】:%dX^%d \n", q->co, q->ex);
    return 1;               //插入成功,返回1
}
 
/**
 * 初始化两个多项式,插入一些测试数据,并打印
 * @param p
 * @param q
 * @return
 */
int InitPolynomial(Polynomial &p, Polynomial &q) {
    //A(x) = 2 + 4x^3^ - x^6^ + 5x^7^ 和 多项式 B(x) = x^3^ + 2x^7^ - 2x^8^
    InsertNode(p, 2, 0);
    InsertNode(p, 4, 3);
    InsertNode(p, -1, 6);
    InsertNode(p, 5, 7);
    printPolynomial(p);
 
    InsertNode(q, 1, 3);
    InsertNode(q, 2, 7);
    InsertNode(q, -2, 8);
    printPolynomial(q);
}
 
//a和b两个多项式相加,相加的结果合并到a
int Addition (Polynomial &a, Polynomial &b){
    if (a == NULL || b == NULL)
        return 0;       //两个多项式不能为空
 
    struct PoNode *p=a, *q=b;      //p、q 两个指针遍历a、b两个单链表
    struct PoNode *pPre=NULL;      //pPre 用于记录 p 的前驱
    while (p!=NULL && q!= NULL) {
        if (p->ex < q->ex) {            //p结点的指数更小
            pPre = p;
            p = p->next;
        } else if (p->ex > q->ex) {     //q结点的指数更小,将q插入到p之前
            if (pPre == NULL){
                //p是单链表a的第一个结点,那么要将q前插到p之前,只能修改头指针a
                a = q;
                q = q->next;
                a->next = p;
                pPre = a;
            } else {
                struct PoNode * s = q;
                q = q->next;
                s->next = p;
                pPre->next = s;     //前插
                pPre = s;
            }
        } else {          //p和q所指结点的指数相同,则统一合并到p
            p->co += q->co;
            pPre = p;
            p = p->next;
            struct PoNode * s = q;
            q = q->next;
            free(s);
        }
    }
    if (p==NULL) {  //p==NULL,说明多项式b中还有一些项没有合并
        pPre->next = q;
    }
}
 
/*

6 对单链表实现基数排序 (对应:补充算法题第二题)

大家可以在自己电脑上新建一个 C++ 项目,并把这段代码复制到 main 函数前边,然后在你的 main 函数里调用 test_RadixSort() 这个函数。跑一跑看看效果

提示:用电脑网页版看,体验更好一些

注:这段代码对应强化课“补充算法题”第二题

// 个人微博:@王道咸鱼学长-计算机考研
// 注:这段代码对应强化课“补充算法题”第二题
// 这段代码实现了关键字0~999范围的"基数排序"
 
#ifndef CODE_RADIXSORT_H
#define CODE_RADIXSORT_H
 
#include "random"
#include "stdio.h"
 
//用于存储关键字的结点
typedef struct RaNode {
    int key;
    struct RaNode * next;
} Node;
 
//队列结点定义
typedef struct {
    RaNode * front;    //队头指针
    RaNode * rear;     //队尾指针
} Queue;
 
//取出关键字 key 的第 d 位(第1位是个位,第2位是十位,第3位是百位
int getRadix(int key, int d){
    if(d==1) return key % 10;
    if(d==2) return (key/10) % 10;
    if(d==3) return (key/100) % 10;
    return -1;  //参数d有误
}
 
//第 k 趟分配
void distribute (RaNode * head, int k, Queue list[]) {
    //每次摘下链头元素进行分配
    while (head->next!=NULL){
        RaNode * p = head->next;          //p指向链头元素
        head->next = p->next;           //摘下链头元素
        p->next=NULL;
 
        int r = getRadix(p->key, k);    //取出当前结点第k位
        //目前第r个分配队列为空
        if (list[r].front == NULL){
            list[r].front = p;          //将结点p插入第r个队列
            list[r].rear = p;
        } else {
            list[r].rear->next = p;     //将结点p插入第r个队列的队尾
            list[r].rear = p;           //修改队尾指针
        }
    }
}
 
//第 k 趟回收
void collect(RaNode * head, int k, Queue list[]) {
    //依次将 9~0 队列中的元素整体摘下,用头插法插入单链表 head
    for (int i=9; i>=0; i--) {
        if (list[i].front == NULL) continue;    //空队列直接跳过
        list[i].rear->next = head->next;        //将第i个分配队列整体头插到链表中
        head->next = list[i].front;
        list[i].front = NULL;
        list[i].rear = NULL;
    }
}
 
//对单链表 head 进行基数排序,其中指针 head 指向头结点
int RadixSort(RaNode * head) {
    Queue list[10];  //用于实现基数排序的10个队列
    for (int i=0; i<10; i++){
        list[i].front = NULL;
        list[i].rear = NULL;
    }
    //由于关键字取值范围为 0~999,因此仅需 3 趟分配/回收
    for (int r=1; r<=3; r++){
        distribute(head, r, list);
        collect(head, r, list);
    }
}
 
//打印单链表的值
void printList (RaNode * head) {
    RaNode * p = head;
    printf("【链表的值】:");
    while (p->next!=NULL) {
        printf("%d ", p->next->key);
        p = p->next;
    }
    printf("\n");
}
 
 
//【测试代码】:实现对单链表的基数排序,关键字范围是 0~999
//先随便建立一个乱序的带头结点单链表,再对单链表进行基数排序
int test_RadixSort() {
    //新建一个带头结点的乱序单链表
    RaNode * head = (RaNode *) malloc (sizeof(RaNode));
    head->next = NULL;
    //随机插入一些数据到 单链表 head 中
    for (int i=0; i<100; i++){
        RaNode * p = (RaNode *) malloc (sizeof(RaNode));
        p->key = rand() % 1000;     //此处rand函数生成随机整数,对1000取余数,关键字范围控制在0~999以内
        p->next = head->next;
        head->next = p;
    }
 
    printList(head);
    RadixSort(head);
    printList(head);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值