用链表实现“啦啦啦”等算法或数据结构(持续更新)

本文介绍了使用链表实现冒泡排序和快速排序的方法,并详细展示了如何通过链表进行重复数值的删除、构建扩展二叉树等操作。此外,还探讨了如何通过已知的遍历顺序来重构二叉树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.冒泡排序

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
struct node
{
    int data;
    struct node *next;
}*head,*p,*q,*tail;

int main()
{
    int i,n,t;
/*-------------------------------------------------------*/    
    scanf("%d",&n);
    head=(struct node*)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;
    for (i=1;i<=n;i++)
    {
        p=(struct node*)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;
    }//读入
/*-------------------------------------------------------*/    
    for (p=head->next;p!=NULL;p=p->next)
        for (q=p->next;q!=NULL;q=q->next)
            if (p->data>q->data)
            {
                t=p->data;
                p->data=q->data;
                q->data=t;
            }
    //上面的是用链表实现的冒泡排序;
 /*-------------------------------------------------------*/   
    p=head->next;
    printf("%d",p->data);
    while (p->next!=NULL)
    {
        printf(" %d",p->next->data);
        p=p->next;
    }
    //输出有序链表;
    return 0;
}

2.快速排序(本地AC就是AC了,OJ上TLE都是假的)

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
struct Node
{
    int data;
    struct Node *next;
}*head,*p,*tail;
/*-------------------------------------------------------*/ 
void QuickSort(struct Node *head,struct Node *tail)
{
    if(head == NULL||head == tail) return ;
    int pivot = head->data;
    struct Node *p = head;
    struct Node *q = p->next;
    while(q != tail)
    {
        if(q->data <pivot) //每次都选择待排序链表的头结点作为划分的基准
        {
            p = p->next;
            int tmp = p->data; //p指针指向比基准小的节点组成的链表
            p->data = q->data;
            q->data =tmp;
        }
        q=q->next;
    }
    int tmp = p->data; 
    //此时p指向比基准小的节点组成的链表的最后一个节点,也就是基准元素,所以要与基准元素交换
    p->data = head->data;
    head->data =tmp;
    QuickSort(head,p); 
    //比基准元素小的链表
    QuickSort(p->next,NULL); 
    //右边是比基准大的节点组成的链表
}
//MMP比冒泡都慢的快排
/*-------------------------------------------------------*/ 
int main()
{
    int i,n;
    head=(struct Node *)malloc(sizeof(struct Node));
    head->next=NULL;
    tail=head;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        p=(struct Node *)malloc(sizeof(struct Node));
        scanf("%d",&p->data);
        p->next=NULL;
        tail->next=p;
        tail=p;
    }
    QuickSort(head,tail);
    p=head->next;
    while(p!=NULL)
    {
        printf("%d ",p->data);
        p=p->next;
    }
    printf("\n");
    return 0;
}

3.重复数值的删除

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
struct node
{
    int data;
    struct node *next,*fron;
}*head,*p,*tail,*q,*r;
/*-------------------------------------------------------*/
int main()
{
    int i,n,num=0;
    scanf("%d",&n);

    head=(struct node*)malloc(sizeof(struct node));
    head->next=NULL;
    tail=head;
    for (i=1;i<=n;i++)
    {
        p=(struct node*)malloc(sizeof(struct node));
        scanf("%d",&p->data);
        p->next=head->next;
        head->next=p;
    }
    //逆序建立链表
/*-------------------------------------------------------*/    
    p=head->next;
    q=p;
    while (p!=NULL)
    {
        while (q->next!=NULL)
        {
            if (p->data==q->next->data)
            {
                r=q->next;
                q->next=r->next;
                free(r);
                num++;
            }
            else q=q->next;
        }
        p=p->next;
        q=p;
    }
    //重复数值删除
/*-------------------------------------------------------*/
    printf("%d\n",n-num);
    p=head->next;
    printf("%d",p->data);
    while (p->next!=NULL)
    {
        printf(" %d",p->next->data);
        p=p->next;
    }
    printf("\n");
    //输出删减完毕后的链表
/*-------------------------------------------------------*/
    return 0;
}

4.扩展二叉树

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdlib.h>
struct tree
{
    char a;
    struct tree *lchild,*rchild;//二叉树的左右子树
};
char s[233];
int i,j,k;
struct tree *root;//记录根节点

struct tree * build(struct tree *t);
void printzx(struct tree *t);
void printhx(struct tree *t);
void del(struct tree *t);
void printchild(NODE *t);
int printdeep(NODE *t);
int main()
{
    struct tree *t;
    char c;
    while (~scanf("%s",s))
    {
        root=NULL;//这里根节点要初始化,不然对于空树情况会出错
        scanf("%c",&c);
        i=-1;
        t = build(t);
        printzx(root);
        printf("\n");
        printhx(root);
        printf("\n");
        //del(root);del函数有毛病,没有调用
    }
    return 0;
}

struct tree * build(struct tree *t)
//因为要用链表建树
//所以这里吧建树函数定义成struct tree *类型的
//主要目的是把建立的各个节点链接起来
{
     i++;
     if (s[i]!=',')
     {
         t=(struct tree *)malloc(sizeof(struct tree));
         t->a=s[i];
         if (i==0) root=t;
         t->lchild = build(t->lchild);
         t->rchild = build(t->rchild);
         //这里是把新建立的节点连接起来
         //如果没有这句话,相当于新建立了很多节点而没有把这些节点链接起来
         //至于为什么会这样,需要自己慢慢体会
     }
     else t=NULL;
     return t;
}

void printzx(struct tree *t)
//输出中序遍历
{
    if (t!=NULL)
    {
        printzx(t->lchild);
        printf("%c",t->a);
        printzx(t->rchild);
    }
    else return;
}

void printhx(struct tree *t)
//输出后序遍历
{
    if (t!=NULL)
    {
        printhx(t->lchild);
        printhx(t->rchild);
        printf("%c",t->a);
    }
    else return;
}

void del(struct tree *t)
//删除整棵树
{
    if (t!=NULL)
    {
        del(t->lchild);
        del(t->rchild);
        free(t);
    }
    else return;
}

void printchild(NODE *t)
//找叶子节点的个数
{
    if (t==NULL) return;
    if (t->lchild!=NULL) printchild(t->lchild);//如果左边有孩子就搜左边
    if (t->rchild!=NULL) printchild(t->rchild);//如果右边有孩子就搜右边
    if (t->rchild==NULL&&t->lchild==NULL) num++;//printf("%c",t->a);
    //如果两边都没有孩子说明是叶子节点
    return;
}

int printdeep(NODE *t)
{
    if (t!=NULL)
    {
        int nleft=printdeep(t->rchild);
        //如果左边可以递归就递归左边,右边可以就递归右边
        int nright=printdeep(t->lchild);
        return nleft>nright?nleft+1:nright+1;
        //返回值是左右边深度的最大值+1
    }
    return 0;
}

5.已知先序遍历求后续遍历(已知后序遍历和中序遍历求先序遍历)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
typedef struct tree
{
    char a;
    struct tree *lchild,*rchild;
}TREE;

TREE *build(int n,char *pre,char *mid);
int main()
{
    char pre[233],mid[233];
    scanf("%s%s",pre,mid);
    build(strlen(pre),pre,mid);
    printf("\n");
    return 0;
}

TREE *build(int n,char *pre,char *mid)
//已知先序中序求后续
{
    TREE *root;
    int i=0;
    if (n==0) return NULL;
    while (pre[0]!=mid[i]) i++;
    //找到根节点在后序遍历的位置
    root=(TREE *)malloc(sizeof(TREE));
    root->a=pre[0];
    //前序遍历的第一个字符必然是根节点
    root->lchild=build(i,pre+1,mid);
    //左子树的长度,左子树在先序遍历的开始地址,左子树在中序遍历的开始地址
    root->rchild=build(n-i-1,pre+i+1,mid+i+1);
    //右子树的长度,右子树在先序遍历的开始地址,右子树在中序遍历的开始地址
    printf("%c",root->a);
    //输出后续遍历
    return root;
}

TREE *build(int n,char *fina,char *mid)
//已知中序后序求前序
{
    TREE *root;
    int i=0;
    if (n<=0) return NULL;
    while (mid[i]!=fina[n-1]) i++;
    root=(TREE *)malloc(sizeof(TREE));
    root->a=fina[n-1];
    printf("%c",root->a);
    //后序遍历:____left____right_root
    //中序遍历:____left_root____right
    root->lchild=build(i,fina,mid);
    root->rchild=build(n-i-1,fina+i,mid+i+1);
    return root;
}

6.双向队列(其实就是双向链表)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define true 1
#define false 0
struct node
{
    int data;
    struct node *left,*right;
}*head,*p,*tail;
char LIN[]="LIN",RIN[]="RIN",LOUT[]="LOUT",ROUT[]="ROUT";

struct node *leftadd(struct node *head,int x);
struct node *rightadd(struct node *tail,int x);
_Bool leftdel(struct node *head);
_Bool rightdel(struct node *tail);
int main()
{
    int n,i,x,a[10001];
    char type[23];
    scanf("%d",&n);
    for (i=0; i<=n; i++) a[i]=0;
    head=(struct node *)malloc(sizeof(struct node));
    head->right=NULL;
    tail=head;
    for (i=1; i<=n; i++)
    {
        scanf("%s",type);
        if (!strcmp(type,LIN))
        {
            scanf("%d",&x);
            head=leftadd(head,x);
        }
        else if (!strcmp(type,RIN))
        {
            scanf("%d",&x);
            tail=rightadd(tail,x);
        }
        else if (!strcmp(type,LOUT))
        {
            if (leftdel(head)) continue;
            else a[i]=1;
        }
        else if (!strcmp(type,ROUT))
        {
            if (rightdel(tail)) continue;
            else a[i]=1;
        }
    }
    p=head->right;
    while (p->right!=NULL)
    {
        printf("%d ",p->data);
        p=p->right;
    }
    printf("%d\n",p->data);
    for (i=0; i<=n; i++) if (a[i])
            printf("%d ERROR\n",i);
    return 0;
}

struct node *leftadd(struct node *head,int x)
{
    p=(struct node *)malloc(sizeof(struct node));
    p->data=x;
    p->right=head->right;
    head->right=p;
    head->right->left=p;
    return head;
}

struct node *rightadd(struct node *tail,int x)
{
    p=(struct node *)malloc(sizeof(struct node));
    p->data=x;
    p->right=NULL;
    p->left=tail;
    tail->right=p;
    tail=p;
    return tail;
}

_Bool leftdel(struct node *head)
{
    if (head->right==NULL) return false;
    else
    {
        struct node *r;
        r=head->right;
        r->right=head->right;
        free(r);
    }
    return true;
}

_Bool rightdel(struct node *tail)
{
    if (tail==head) return false;
    else
    {
        struct node *r;
        r=tail->left;
        tail->left=r->left;
        tail=r->left;
        free(r);
    }
    return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

nine_mink

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

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

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

打赏作者

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

抵扣说明:

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

余额充值