用递归删除各种节点

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

#define MAXSIZE 1000
typedef int ElemType;
typedef struct node{    //定义链表节点类型
    ElemType data;
    struct node * next;
} Node;
typedef Node *LinkedNode;

/*[1] 求以h为头指针的单链表的节点个数 */
int GetNodeNum(LinkedNode &h)
{
    if(h==NULL)
        return 0;
    else
        return GetNodeNum(h->next) + 1;
}
/*[2] 正向显示以h为头指针的单链表的所有节点值 */
void PrintForward(LinkedNode &h)
{
    if(h==NULL)    //链表到头,结束输出
        return ;
    printf("%d ",h->data);
    PrintForward(h->next);    //输出下一个元素值
}
/*[3] 反向显示以h为头指针的单链表的所有节点值 */
void PrintReverse(LinkedNode &h)
{
    if(h==NULL)
        return ;
    PrintReverse(h->next);    //链表跑到头,再开始输出
    printf("%d ",h->data);
}
/*[4] 删除以h为头指针的单链表中值为x的第一个节点 */
bool DeleteFirstX(LinkedNode &h,ElemType x)
{
    //递归出口
    if(h==NULL)
        return false;
    else if(h->data==x){        //第一个节点就是要找的节点,删除
        if(h->next==NULL){    //只有一个节点
            free(h);
            h = NULL;
            return true;
        }
        LinkedNode p;
        p = h;
        h = h->next;
        free(p);
        return true;
    }
    else if(h->next!=NULL){
        if(h->next->data==x){    //找到节点,删除
            LinkedNode p;
            p = h->next;
            h->next = p->next;
            free(p);
            return true;
        }
    }
    //递归体
    if(DeleteFirstX(h->next,x))
        return true;
    else
        return false;
}
/*[5] 删除以h为头指针的单链表中值为x的所有节点 */
void DeleteAllX(LinkedNode &h,ElemType x)
{
    if(h==NULL)
        return ;
    if(h->data==x){        //第一个节点就是要找的节点,删除
        if(h->next==NULL){    //只有一个节点
            free(h);
            h = NULL;
            return ;
        }
        LinkedNode p;
        p = h;
        h = h->next;
        free(p);
        DeleteAllX(h,x);
    }
    else if(h->next==NULL)    //递归出口
        return ;
    else if(h->next->data==x){    //找到节点,删除
        LinkedNode p;
        p = h->next;
        h->next = p->next;
        free(p);
        DeleteAllX(h,x);
    }
    else
        DeleteAllX(h->next,x);
}

/*[6] 删除以h为头指针的单链表中最大节点值 */
void DeleteMaxNode(LinkedNode &h,LinkedNode c,LinkedNode p)
{
    if(h==NULL)
        return ;
    if(c->next==NULL){    //到头,开始删除
        if(p->next ==NULL){
            free(p);
            h = NULL;
            return ;
        }
        if(p==h && p->data > p->next->data){    //第一个节点是要删除的节点
            h = h->next;
            free(p);
            return ;
        }
        else{
            LinkedNode q = p->next;
            p->next = q->next;
            free(q);
            return ;
        }
    }
    if(c->next->data > p->next->data)
        p = c;
    DeleteMaxNode(h,c->next,p);
}
/*[7] 删除以h为头指针的单链表中最小节点值 */
void DeleteMinNode(LinkedNode &h,LinkedNode c,LinkedNode p)
{
    if(h==NULL)
        return ;
    if(c->next==NULL){    //到头,开始删除
        if(p->next ==NULL){
            free(p);
            h = NULL;
            return ;
        }
        if(p==h && p->data < p->next->data){    //第一个节点是要删除的节点
            h = h->next;
            free(p);
            return ;
        }
        else{
            LinkedNode q = p->next;
            p->next = q->next;
            free(q);
            return ;
        }
    }
    if(c->next->data < p->next->data)
        p = c;
    DeleteMinNode(h,c->next,p);
}

/* 1. 初始化单链表 */
LinkedNode LinkedListInit()
{
    LinkedNode head = (Node*)malloc(sizeof(Node));
    head->next = NULL;
    return head;
}

/* 2. 清空单链表 */
void LinkedListClear(LinkedNode &L)
{
    //L为头指针
    while(L){    //依次清空节点,直到头指针指向的下一个节点的地址为空
        LinkedNode t;
        t = L;
        L = t->next;
        free(t);
    }
    return ;
}

/* 3. 用尾插法建立单链表 */
LinkedNode  LinkedListCreat( LinkedNode L,ElemType a[],int n )    //讲数组a中的元素以尾插法放入链表中
{
    int i;
    LinkedNode p = L;
    p->data = a[1];
    for(i=2;i<=n;i++){
        LinkedNode q = (LinkedNode)malloc(sizeof(Node));
        q->data = a[i];
        q->next = NULL;
        p->next = q;
        p = q;
    }
    return L;
}

int Menu()
{
    int in;
    printf("[1] 重新建立一个链表\n");
    printf("[2] 求以h为头指针的单链表的节点个数\n");
    printf("[3] 正向显示以h为头指针的单链表的所有节点值\n");
    printf("[4] 反向显示以h为头指针的单链表的所有节点值\n");
    printf("[5] 删除以h为头指针的单链表中值为x的第一个节点\n");
    printf("[6] 删除以h为头指针的单链表中值为x的所有节点\n");
    printf("[7] 删除以h为头指针的单链表中最大节点值\n");
    printf("[8] 删除以h为头指针的单链表中最小节点值\n");
    printf("[0] 按其他键退出\n");
    scanf("%d",&in);
    return in;
}
LinkedNode Reply(LinkedNode head,int in)
{
    int i,n,x;
    int a[MAXSIZE+1];
    switch(in){
        case 1:    //重新建立一个链表
            LinkedListClear(head);
            head = LinkedListInit();
            printf("你要输入多少个数据?\n");
            scanf("%d",&n);    //输入链表大小
            printf("请依次输入数据:\n");
            for(i=1;i<=n;i++)
                scanf("%d",&a[i]);
            head = LinkedListCreat(head,a,n);
            printf("链表建立成功!\n");
            break;

        case 2:    //求以h为头指针的单链表的节点个数
            printf("单链表的节点个数为:%d\n",GetNodeNum(head));
            break;

        case 3:    //正向显示以h为头指针的单链表的所有节点值
            printf("链表中元素依次为(正向):\n");
            PrintForward(head);
            printf("\n");
            break;

        case 4:    //反向显示以h为头指针的单链表的所有节点值
            printf("链表中元素依次为(反向):\n");
            PrintReverse(head);
            printf("\n");
            break;

        case 5:    //删除以h为头指针的单链表中值为x的第一个节点
            printf("输入你要删除的元素的值?\n");
            scanf("%d",&x);
            if(DeleteFirstX(head,x))
                printf("删除成功!\n");
            else
                printf("删除失败!\n");
            printf("链表中元素依次为(正向):\n");
            PrintForward(head);
            printf("\n");
            break;

        case 6:    //删除以h为头指针的单链表中值为x的所有节点
            printf("输入你要删除的元素的值?\n");
            scanf("%d",&x);
            n = GetNodeNum(head);
            DeleteAllX(head,x);
            i = GetNodeNum(head);
            if(n!=i)
                printf("删除成功!\n");
            else
                printf("删除失败!\n");
            printf("链表中元素依次为(正向):\n");
            PrintForward(head);
            printf("\n");
            break;

        case 7:    //删除以h为头指针的单链表中最大节点值
            n = GetNodeNum(head);
            DeleteMaxNode(head,head,head);
            i = GetNodeNum(head);
            if(n!=i)
                printf("删除成功!\n");
            else
                printf("删除失败!\n");
            printf("链表中元素依次为(正向):\n");
            PrintForward(head);
            printf("\n");
            break;

        case 8:    //删除以h为头指针的单链表中最小节点值
            n = GetNodeNum(head);
            DeleteMinNode(head,head,head);
            i = GetNodeNum(head);
            if(n!=i)
                printf("删除成功!\n");
            else
                printf("删除失败!\n");
            printf("链表中元素依次为(正向):\n");
            PrintForward(head);
            printf("\n");
            break;

        default:
            printf("Bye~\n");
            exit(1);
    }
    system("pause");
    system("cls");
    return head;
}
int main()
{
    int in;    //存储输入命令
    LinkedNode head = NULL;
    while(1){
        in = Menu();
        head = Reply(head,in);    //响应命令
    }
    return 0;
}
时间: 2024-11-05 22:51:48

用递归删除各种节点的相关文章

关于递归删除链表节点为什么不会断链问题解释

问题的由来:    当你第一次实现用递归实现链表删除功能的时候,是否有一丝丝的考虑过.这个问题呢?为什么对于非递归版本的删除必须要知道当前要删除节点的前驱,而需要对其前驱节点的next域指针进行修改.而递归删除却不需要呢?难道这样不会造成链表的断链吗? 好了.我们开始抽象出我们今天要解决的问题. 问题一: 递归实现链表节点的删除和非递归删除的区别是什么? 问题二: 为什么在使用递归删除的时候链表不会断链? 先给个代码,好根据代码模拟,不会空想. 函数的递归模型: 终止条件: f(L,x) = 不

【DRP】树形结构操作之递归删除

如图所示呈现了一颗树形结构.本文从删除树形结构的任意结点出发,提供了一种解决思路 图中,不包含其它结点的是叶子结点.包含其他结点的是父结点,即不是叶子结点. 一 本文的知识点: (1)递归调用: 因为待删除的结点的层次是不确定的,如果是叶子结点则可以直接获取id直接删除,如:北京中医医院.华北区.如果待删除的结点是父结点,则需要继续向下查询,依次遍历出其子结点,从下往上依次删除,如'华北区'.因此我们使用递归调用. (2)保证事务的原子性 假设待删除的结点是'华北区',则相当于删除了3条信息(华

树节点递归删除--service层

@Service public class ContentCategoryServiceImpl extends BaseServiceImpl<ContentCategory> implements ContentCategoryService { @Override public void deleteContentCategory(Long parentId, Long id) { // 声明存放需要删除的节点的容器 List<Object> ids = new ArrayL

使用mysql 游标,快速删除子节点及其附属节点

上篇,我写的是如何用数据存储,并通过html展示出树形的结构, 本篇我将讲述,如何通过存储过程,删除一个树节点及其附属节点.网上已经有非常多的关于mysql 游标使用的文章了, 为什么我还要写这篇文章呢,主要是想表达一些在软件设计领域的一些想法. 我不赞同在数据库中大量的使用存储过程, 因为我觉得随着软件系统的复杂度逐渐提高,维护的难度会逐渐的增大.而且大批量的使用存储过程,不利于后期通过分布式部署应用程序来解决日益增多的业务需求. 我推荐把存储过程用在处理一些不包含太多业务,批量操作数据的场景

删除 treeview Node节点 循环删除子节点 存储过程

create  procedure  DeleteNote @Objid int--定义要删除树节点 as declare @childID int  --声明变量 declare cursors cursor local for select Objid from TableChart where [email protected]      --local关键字全局游标 open cursors fetch next from cursors into @childID     --取游标的

list链表之:从链表删除一个节点list_del

从链表删除一个节点使用接口list_del,使用list_del时要非常注意. list_del的实现如下: static inline void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; } static inline void __list_del(struct

java递归删除文件及目录

package base; import java.io.File; public class delete { public static void main(String[] args) { deleteFileAndFoder("../yang"); } static void deleteFileAndFoder(String path){ File f=new File(path); if(f.isDirectory()){//假设是文件夹.先递归删除 String[] li

剑指Offer之在O(1)时间删除链表节点

题目描述 给定单向链表的头指针和一个节点指针,定义一个函数在O(1)时间删除该节点. 解题思路 在单向链表中删除一个节点,最常规的做法无疑是从链表的头结点开始,顺序的遍历查找要删除的节点,并在链表中删除该节点.这种思路由于需要顺序查找,时间复杂度自然就是$O(n)$了. 之所以需要从头开始查找,是因为我们需要得到将删除的节点的前面一个节点.在单向链表中,节点中没有指向前一个节点的指针,所以只好从链表的头结点开始顺序查找.那是不是一定需要得到被删除的节点的前一个节点呢?答案是否定的.我们可以很方便

js添加、修改、删除xml节点例子

version="1.0" encoding="gb2312"?> 02. <bookstore> 03. <book genre="fantasy" isbn="2-3631-4"> 04. <title>Oberons Legacy</title> 05. <author>Corets, Eva</author> 06. <price>