c语言程序记录

基数排序算法:

#include <stdio.h>
// 获取数组中的最大值
int getMax(int arr[], int n) {
    int max = arr[0];
    for (int i = 1; i < n; i++) {
        if (arr[i] > max)
            max = arr[i];
    }
    return max;
}


/**
 * 基数排序函数
 * 排序的次数根据序列的最大数确定,最大数是三位数,循环三次,最大数是四位数,循环四次,从个位数
 * 开始排,依次是个,十,百,千,万...
 * 每次排序需要用到十个桶,分别是0号桶,1号桶,2号桶...一直到9号桶,将对应元素放在各自桶中
 * 比如刚开始排个数,将个位数是0的放在0号桶,个位数是1的放在1号桶... 将所有的元素放入桶之后,
 * 再依次从桶中取出,形成一个新的待排序列,然后按照相同的方式再排十位数,百位数...

 时间复杂度:
 基数排序的时间复杂度取决于数据的位数和桶的数量。假设数据的位数为 d,桶的数量为 k,数据的个数为n。
1. 对于每一位的分配和收集步骤,需要遍历整个数组,时间复杂度为 O(n)。
2. 对于位数的迭代,最多进行 \( d \) 次迭代。每次迭代需要进行一次分配和收集步骤,因此总时间复杂度为 O(d * n)。
因此,基数排序的总时间复杂度为  O(d * (n + k))。在数据的位数 d, 较小且桶的数量 k, 不是很大的情况下,
 时间复杂度通常可以近似为 O(n)。

 空间复杂度
 基数排序的空间复杂度取决于额外空间的使用情况,主要包括临时存储排序结果的数组和存储每个桶中元素个数的数组。
1. 临时存储排序结果的数组:它的大小与待排序数组的大小相同,因此空间复杂度为 O(n)。
2. 存储每个桶中元素个数的数组:这个数组的大小是固定的,与桶的数量 k 相关,因此空间复杂度为 (k)。

因此,基数排序的总空间复杂度为O(n + k)。在数据量较大、桶的数量较大时,空间复杂度会相对较高。
 
是稳定排序算法
 
 * @param arr
 * @param n
 * @return
 */
void radixSort(int arr[], int n) {
    // 找到数组中的最大值,以确定迭代次数
    int max = getMax(arr, n);

    // 用于临时存储排序结果的数组
    int output[n];

    // 定义一个count数组,用于存储每个桶中元素的个数
    int count[10];

    // 初始化count数组
    for (int i = 0; i < 10; i++)
        count[i] = 0;

    // 计算每个桶中元素的个数
    for (int exp = 1; max / exp > 0; exp *= 10) {
        // 清零count数组
        for (int i = 0; i < 10; i++)
            count[i] = 0;

        // 统计每个桶中元素的个数
        for (int i = 0; i < n; i++)
            count[(arr[i] / exp) % 10]++;

        // 更新count数组,使其包含当前桶中元素的最终位置
        for (int i = 1; i < 10; i++)
            count[i] += count[i - 1];

        // 生成排序结果
        for (int i = n - 1; i >= 0; i--) {
            output[count[(arr[i] / exp) % 10] - 1] = arr[i];
            count[(arr[i] / exp) % 10]--;
        }
        printf("\n");

        // 将排序结果复制回原数组
        for (int i = 0; i < n; i++) {
            printf("%d,", output[i]);
            arr[i] = output[i];
        }
        printf("\n");

    }
}

// 打印数组
void printArray(int arr[], int n) {
    for (int i = 0; i < n; i++)
        printf("%d ", arr[i]);
    printf("\n");
}

int main() {
    int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};
    int n = sizeof(arr) / sizeof(arr[0]);
    printArray(arr, n);
    radixSort(arr, n);
    printf("排序后的数组:\n");
    printArray(arr, n);
    return 0;
}


双链表:尾插法建立双链表,删除节点,查找节点

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

//双向循环链表
typedef struct DuLNode {
    int data;
    struct DuLNode *prior;//直接前驱指针
    struct DuLNode *next;//直接后继指针
} *DList, DLNode;

DLNode *BuyNode() {
    DLNode *node = (DLNode *) malloc(sizeof(DLNode));
    return node;
}

/**
 * 尾插法建立链表
 * @param l
 * @param len
 */
void InitDListByTail(DLNode **l, int len) {
    DLNode *head = BuyNode();
    if (!head) {
        printf(" InitListByTail fail .");
    }
    *l = head;
    DLNode *r = head;
    while (len > 0) {
        int data = random() % 20;
        DLNode *node = BuyNode();
        if (!node) {
            printf(" buy node fail .");
        }
        node->data = data;
        r->next = node;
        node->prior = r;
        r = r->next;//指针指向最后一个节点
        len--;
    }
}

/**
 * 按照位置插入,遍历的p指针应该指向插入位置的前一个节点,和单链表一样,还要考虑插入位置是最后
 * 节点情况
 * @param l
 * @param index
 * @param data
 */
void InsertOneByIndex(DLNode *l, int index, int data) {
    if (index < 1) {
        printf(" %d is not fit position,too small ", index);
        return;
    }
    DLNode *p = l;
    while (p && index > 1) {
        p = p->next;
        index--;
    }
    if (index != 1) {
        printf(" %d is not fit position,too big ", index);
        return;
    }
    DLNode *node = BuyNode();
    if (p->next) {//插入位置不是最后一个
        node->next = p->next;
        p->next->prior = node;
    }
    p->next = node;
    node->prior = p;
    node->data = data;
}

DLNode *FindNodeByData(DLNode *l, int data) {
    DLNode *p = l->next;
    while (p) {
        if (p->data == data)
            return p;
        p = p->next;
    }
    return NULL;
}

/**
 * 删除p节点的后继节点
 * @param p
 */
void DeleteNodeByPoint(DLNode *p) {
    if (!p) {
        printf(" this point is null");
        return;
    }
    DLNode *a = p->next;//a指向的节点是要删除的节点
    p->next = a->next;
    a->next->prior = p;
    free(a);
}

void PrintList(DLNode *p) {
    printf("\n print :\n");
    while (p != NULL) {
        printf(" %d ,", p->data);
        p = p->next;
    }
}

int main() {
    printf("Hello World, now we need create a double Linklist !\n");
    DLNode *l;
    InitDListByTail(&l, 5);
    printf("print this new double linklist !\n");
    PrintList(l->next);
    printf("\ninsert one node \n");
    InsertOneByIndex(l, 3, 90);
    PrintList(l->next);
    DLNode *p = FindNodeByData(l, 6);
    printf("\n delete find one %d\n", p->data);
    DeleteNodeByPoint(p);
    PrintList(l->next);
    return 0;
}

两个无序单链表,分别用指针A和B指向,合并成一个非递减单链表,用指针C指向

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

//双向循环链表
typedef struct DuLNode {
    char data;
    struct DuLNode *prior;//直接前驱指针
    struct DuLNode *next;//直接后继指针
} *list, List;

typedef struct LNode {
    int data;
    struct LNode *next;
} Node, *PNode;

PNode BuyNode() {
    PNode node = (PNode) malloc(sizeof(Node));
    return node;
}

/**
 * 尾插法建立链表
 * @param l
 * @param len
 */
void InitListByTail(Node **l, int len) {
    PNode head = BuyNode();
    if (!head) {
        printf(" InitListByTail fail .");
    }
    *l = head;
    PNode t = head;
    while (len > 0) {
        int data = random() % 20;
        Node *node = BuyNode();
        if (!node) {
            printf(" buy node fail .");
        }
        node->data = data;
        t->next = node;
        t = t->next;//指针指向最后一个节点
        len--;
    }
}

/**
 * 将原无序链表变成非递减链表
 * 在不申请新结点的基础上,在原来链表改动每个结点的next指向。
 * 首先使用指针ol指向第一个结点(不是头结点),ol指向的是待排序链表,简称老链表
 * 其次使用h指针指向头结点,将头结点的next置为NULL,h指向的是排序之后的链表,简称新链表
 * 然后每次从老表中找到一个最大的,通过头插法插入到新链表中,直到老表为空
 * @param l
 */
void SetListIncrement(Node **l) {
    Node *p,//用于遍历循环找到最大节点,每次遍历到尾节点
    *h = *l,//新链表的头指针
    *f,//指向
    *oh = (*l)->next,
            *s;//
    h->next = NULL;//新递增链表的头指针
    while (oh) {
        s = oh;
        p = oh;
        f = oh;
        while (p && p->next) {
            //每次找到最大的 用s指向最大值节点
            p = p->next;
            if (p->data > s->data) {
                s = p;//找到最大的
            }
        }
        while (f && f->next) {
            if (f->next == s) {
                break;
            }
            f = f->next;
        }
        //构造递增链表 1原来链表删除该节点 2新递增链表添加该节点
        if (s == oh) {
            oh = oh->next;//旧的单链表头指针不能丢失,永远指向第一个
        } else {
            f->next = f->next->next;//原来的链表保持连贯
        }
        //头插法建立递增单链表
        s->next = h->next;
        h->next = s;
    }
}

/**
 * 合并两个链表
 * @param A
 * @param B
 * @param C
 */
void MergeList(PNode *A, PNode *B, PNode *C) {
    *C = *A;//c指向a的头节点
    Node *p = (*A)->next, *q = (*B)->next, *t = *C;
    while (p != NULL && q != NULL) {
        if (p->data > q->data) {
            t->next = q;
            q = q->next;
        } else {
            t->next = p;
            p = p->next;
        }
        t = t->next;
    }
    if (p != NULL)
        t->next = p;
    if (q != NULL)
        t->next = q;
    free(*B);
}

void PrintList(Node *p) {
    printf("\n print :\n");
    while (p != NULL) {
        printf(" %d ,", p->data);
        p = p->next;
    }
}

void InitIt(list *l) {
    list q = (list) malloc(sizeof(List));
    q->data = 'a';
    *l = q;
}

int main() {
    printf("Hello, World!\n");
    Node *A, *B, *C;
    InitListByTail(&A, 3);
    InitListByTail(&B, 5);
    PrintList(A->next);
    PrintList(B->next);
    SetListIncrement(&A);
    SetListIncrement(&B);
    printf("\n after merge :");
    MergeList(&A, &B, &C);
    PrintList(C->next);
    return 0;
}

线性表的链式存储 带头节点的单链表

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

#define NULL 0
//带头节点的单链表
typedef struct LNode {
    char data;
    struct LNode *next;
} LNode, *LinkList;

LinkList InitLinkList() {
    LinkList head = (LinkList) malloc(sizeof(LNode));
    if (!head) {
        printf("initialize fail !\n");
    }
    head->data = '1';
    head->next = NULL;
    return head;
}

LinkList BuyNode() {
    LinkList node = (LinkList) malloc(sizeof(LNode));
    if (!node) {
        printf("buy fail !\n");
    }
    return node;
}

/**
 * 按照位置插入
 * @param l
 * @param index
 * @param e
 */
void InsertOneByPos(LinkList l, int index, char e) {
    LinkList f = l->next;
    //判断插入位置是否合理
    if (index < 1) {
        printf("this position is not fit !");
        return;
    }
    int len = 0;
    while (f != NULL) {
        f = f->next;
        len++;
    }
    if (len + 1 < index) {
        printf("this position is not fit !");
        return;
    }
    LinkList p = BuyNode();
    LinkList r = l;
    int i = 1;
    //找到插入位置的前一个节点
    while (i < index) {
        r = r->next;
        i++;
    }
    p->next = r->next;
    p->data = e;
    r->next = p;
}

/**
 * 头插入法
 * 比如说当前列表是 head -> h -> e
 * 现在要插入的数据是 a
 * 插入完之后链表内容是:head ->a -> h -> e
 * @param l
 * @param e
 */
void InsertOneFromHead(LinkList l, char e) {
    LinkList p = BuyNode();
    if (!p) {
        printf("apply node fail !\n");
    }
    p->next = l->next;
    p->data = e;
    l->next = p;
}

/**
 * 尾插入法
 * 比如说当前列表是 head -> h -> e
 * 现在要插入的数据是 a
 * 插入完之后链表内容是:head -> h -> e ->a
 * @param l
 * @param e
 */
void InsertOneFromTail(LinkList l, char e) {
    LinkList p = BuyNode();
    LinkList f = l;
    //找到最后一个节点
    while (f->next != NULL) {
        f = f->next;
    }
    p->data = e;
    p->next = f->next;
    f->next = p;
}

//打印链表
void PrintLinkList(LinkList l) {
    printf("\nstart print :\n");
    for (LinkList i = l; i != NULL; i = i->next) {
        printf("%c ", i->data);
    }
}

int main() {
    printf("\nHello, World!\n");
    LinkList l = InitLinkList();
    InsertOneFromTail(l, 'h');
    InsertOneFromTail(l, 'e');
    InsertOneFromTail(l, 'l');
    InsertOneFromTail(l, 'l');
    InsertOneFromTail(l, 'o');
    InsertOneFromTail(l, '.');
    InsertOneByPos(l,8,'X');
    PrintLinkList(l);
    return 0;
}

线性表顺序存储

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

#define LIST_INIT_SIZE 10

//线性表的顺序存储结构
typedef struct {
    char *elem;
    int length;//当前长度
    int list_size;//分配空间的长度
} sqList, *Link;

//初始化
int InitList(sqList *L) {
    L->elem = (char *) malloc(LIST_INIT_SIZE * sizeof(char));
    if (!L->elem) {
        printf("fail");
    } else {
        printf("ok\n");
    }
    L->length = 0;
    L->list_size = LIST_INIT_SIZE;

}

//插入元素
void InsertOne(sqList *l, char e, int i) {
    //先判断位置是否正确
    if (i < 1 || i > LIST_INIT_SIZE) {
        printf("not ok, it's too big position ! \n");
    }
    if (i == 1 && l->length == 0) {
        *l->elem = e;
    } else {
        char *q = l->elem + i-1;
        //找到插入位置
        for (char *p = &l->elem[l->length - 1]; p >= q; --p) {
            *(p + 1) = *p;
        }
        *q = e;
    }
    l->length++;
}

//遍历顺序存储线性表
void PrintList(char *p, int length) {
    printf("\nl.length = %d \n", length);
    char *s = p;
    while (s < p + length) {
        printf("%c ", *s);
        s++;
    }
}

int main() {
    sqList l;
    InitList(&l);
    InsertOne(&l, 'h', 1);
    InsertOne(&l, 'e', 2);
    PrintList(l.elem, l.length);

    return 0;
}

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值