【C语言】双链表的实现与冒泡排序

4 篇文章 0 订阅
3 篇文章 0 订阅

【C语言】双链表的实现与冒泡排序

基于C语言,不做标题党,LInux下GCC通过编译,大致流程(底部附图,源码):

	新建双链表(节点数自定义),对节点data域用随机数种子进行随机赋值,并对该链表进行冒泡排序。
	后续其他排序陆续更新......

全局自定义函数如下:

	//链表新建函数
	LinkList *creat_LinkList() 
	
	//创建101个结点
	void init_LinkList(LinkList *pHeader) 

	//链表data域赋值
	void srand_LinkList(LinkList *pHeader)

	//遍历
	void foreach_LinkList(LinkList *pHeader)

	//链表长度(包含头结点)
	int size_LinkList(LinkList *pHeader) 

	//交换节点
	void swap_LinkList(LinkList *pPre, LinkList *pCurrent) 

	//冒泡排序
	void bubble_Sort(LinkList *pHeader, int size) 

具体代码如下:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LinkList struct Node
#define MAX 100


//创建一个双链表结点
LinkList {
    int data;            //数据域
    LinkList *pre;        //前指针域
    LinkList *next;    //后指针域
};


//链表新建函数
LinkList *creat_LinkList() {
    //新结点分配内存
    LinkList *Node = (LinkList *) malloc(sizeof(LinkList *));

    //判断内存分配成功失败
    if (Node == NULL) {
        printf("Memory distribution fail!\n");
        return NULL;
    }

    //指针域初始化
    Node->pre = NULL;
    Node->next = NULL;

    return Node;
}


//创建101个结点
void init_LinkList(LinkList *pHeader) {
    //判空
    if (pHeader == NULL)
        return;

    //首个带有数据的节点开辟空间
    LinkList *pCurrent = (LinkList *) malloc(sizeof(LinkList *));

    //pHeader与节点衔接
    pHeader->next = pCurrent;
    pCurrent->pre = pHeader;

    //开辟节点个数控制(已存在head与第一个非空结点)
    int num = MAX - 1;        //(100 - 1 + 2)= 101

    while (num) {
        //pCurrent->next开辟空间(带有衔接next指针作用)
        pCurrent->next = (LinkList *) malloc(sizeof(LinkList *));

        //记录pCurrent,便于回滚
        LinkList *pPre = pCurrent;

        //双链表pre指针衔接
        pCurrent->next->pre = pCurrent;

        //回滚
        pCurrent = pCurrent->next;

        //计数
        num--;
    }

    //置空末指针
    pCurrent->next = NULL;

}


//链表data域赋值

void srand_LinkList(LinkList *pHeader) {
    //判空
    if (pHeader == NULL)
        return;

    //辅助指针
    LinkList *pCurrent = pHeader->next;

    //添加随机数种子
    srand((unsigned) time(NULL));

    //首个非空结点赋值
    pCurrent->data = rand() % 500;

    while (pCurrent) {
        //随机赋值500以内整数值
        pCurrent->data = rand() % 300;

        //后移
        pCurrent = pCurrent->next;

    }
}


//遍历
void foreach_LinkList(LinkList *pHeader) {
    //判空
    if (pHeader == NULL)
        return;

    //辅助
    LinkList *pCurrent = pHeader->next;

    //向前遍历指针
    LinkList *temp = pCurrent;

    int num1 = 0;
    //循环遍历
    printf("———————————————————————————————————正遍历—————————————————————————————————————\n");

    while (pCurrent) {
        //print格式
        //printf("%p\t",pCurrent);
        printf("%d\t", pCurrent->data);

        //向前遍历指针
        temp = pCurrent;
        num1++;

        if (num1 % 10 == 0)
            printf("\n");
        //向后
        pCurrent = pCurrent->next;

    }

    //向前遍历(尾节点开始)
    pCurrent = temp;

    int num2 = 0;

    printf("————————————————————————————————————逆遍历————————————————————————————————————\n");
    while (pCurrent) {
        if (pCurrent == pHeader)
            break;

        printf("%d\t", pCurrent->data);

        num2++;

        if (num2 % 10 == 0)
            printf("\n");

        //向前
        pCurrent = pCurrent->pre;

    }
    printf("————————————————————————————————————END————————————————————————————————————\n");

}


//链表长度(包含头结点)
int size_LinkList(LinkList *pHeader) {
    //辅助
    LinkList *pCurrent = pHeader;

    //计数
    int size = 0;

    while (pCurrent) {
        //向后
        pCurrent = pCurrent->next;

        size++;
    }

    return size;
}


//交换节点
void swap_LinkList(LinkList *pPre, LinkList *pCurrent) {

    //指针转换	此处注意6个指针交换
    //pPre与新前驱建立联系
    pPre->pre->next = pCurrent;
    pCurrent->pre = pPre->pre;

    //pCurrent与新后驱建立联系
    pCurrent->next->pre = pPre;
    pPre->next = pCurrent->next;

    //pPre与pCurrent互连
    pPre->pre = pCurrent;
    pCurrent->next = pPre;

}
/******************************排序开始******************************/

//冒泡排序
void bubble_Sort(LinkList *pHeader, int size) {
    //判空
    if (pHeader == NULL) {
        return;
    }

    //初始化辅助指针
    LinkList *pPre = pHeader;
    LinkList *pCurrent = pHeader;

    //循环次数
    int num = size;

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

        //重置指针位置
        pPre = pHeader->next;
        pCurrent = pPre->next;

        for (int j = 1; j < num - i; j++) {
            if (pPre->data > pCurrent->data) {

                //节点尾节点情况
                if (pCurrent->next == NULL) {
                    pPre->next = pCurrent->next;
                    pCurrent->pre = pPre->pre;
                    pCurrent->next = pPre;
                    pPre->pre->next = pCurrent;
                    pPre->pre = pCurrent;
                }
                //非尾节点情况 
                else {
                    //交换节点
                    swap_LinkList(pPre, pCurrent);

                    //pCurrent指针后移到pPre前面
                    pCurrent = pPre->next;
                }
            }

            //pPre->data > pCurrent->data非真情况下
            else {
                pPre = pPre->next;
                pCurrent = pCurrent->next;
            }
        }
    }
}


int main(void) {

    //新建链表
    LinkList *pHeader = creat_LinkList();

    //链表初始化
    init_LinkList(pHeader);

    //链表data域赋值
    srand_LinkList(pHeader);

    //遍历
    foreach_LinkList(pHeader);

    //冒泡
    bubble_Sort(pHeader, size_LinkList(pHeader));

    //交换结点
    //swap_LinkList(pHeader->next,pHeader->next->next);
    //printf("%d\n", pHeader->next->data);
    //printf("%d\n", pHeader->next->next->data);

    //遍历
    foreach_LinkList(pHeader);
    printf("***************%d\n", size_LinkList(pHeader));

    return 0;
}


节点转换图:

运行效果图(第一次正逆遍历是初始化后的,第二次是排序后的):
在这里插入图片描述
-------------------------------------------------------END-------------------------------------------------------

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我姥爷是校长

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值