• 释放链表内存 void release_link(Link * head) { Link p; p = *head; if(p == NULL) { printf(&quot;link is empty!\n&quot;); } else { while(*head != NULL) { *...
释放链表内存
void release_link(Link * head)
{
Link p;
p = *head;
if(p == NULL)
{
printf("link is empty!\n");
}
else
{
while(*head != NULL)
{
*head = (*head)->next;
free(p);
p = *head;
}
}
}


使链表反序【重要】

void link_reverse(Link * head)
{
Link p1,p2,p3;
p1 = p2 = p3= *head;

if(p1 == NULL)
{
printf("Link is empty!\n");
}
else if(p1->next == NULL)
{
printf("Link is only one.\n");
}
else
{
p2 = p1->next;
if(p2->next == NULL)
{
p2->next = p1;
p1->next = NULL;
*head = p2;
}
else
{
p3 = p2->next;
while(p3->next != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
p3->next = p2;
(*head)->next = NULL;
*head = p3;
}
}

}


带表头结点的链表
创建+头插+尾插+中间插入+删除+反序
#include <stdio.h>
#include <stdlib.h>

#define MAL_ERR 0
#define MAL_OK 1

struct node
{
int num;
struct node * next;
};

typedef struct node Node;
typedef struct node * Link;

int malloc_ok(Link new_node)  //判断空间是否创建成功
{
if(new_node == NULL)
{
return MAL_ERR;
}
else
{
return MAL_OK;
}
}

void create_node(Link * new_node, int i)  //创建空间
{
(*new_node) = (Link)malloc(sizeof(Node));

while(malloc_ok(*new_node) == MAL_ERR)
{
(*new_node) = (Link)malloc(sizeof(Node));
}
(*new_node)->num = i;
}

void create_link(Link *  head)  //创建带表头结点的链表
{
create_node(head,0);
(*head)->next = NULL;
}
void insert_node_head(Link head,Link new_node)  //头插
{
new_node->next = head->next;
head->next = new_node;
}

void insert_node_tail(Link head,Link new_node)   //尾插
{
Link p;
p = head;
while(p->next != NULL)
{
p = p->next;
}
p->next = new_node;
new_node->next = NULL;

}

void insert_node_mid(Link head,Link new_node,int num_loc)  //中间插入
{
Link p,q;
q = head;
p = head->next;

if(p == NULL)
{
head->next = new_node;
new_node->next = NULL;
}
else
{
while(p->num != num_loc && p->next != NULL)
{
q = p;
p = p->next;
}
}
if(p->next == NULL && p->num != num_loc)
{
p->next = new_node;
new_node->next = NULL;
}
else
{
q->next = new_node;
new_node->next = p;
}
}

void display(Link head)   //打印链表
{
Link p;
p = head;

if(p == NULL)
{
printf("no fine Link\n");
}

if(p->next == NULL)
{
printf("Link is empty!\n");
}
else
{
while(p->next != NULL)
{
p = p->next;
printf("num = %d\n",p->num);
}
}
}

void node_del(Link head,int num_val)  //删除一个数
{
Link p,q;
q = head;
p = head->next;

if(p == NULL)
{
printf("链表为空！\n");
}
else
{
while(p->num != num_val && p->next != NULL)
{
q = p;
p = p->next;
}
if(p->next == NULL && p->num != num_val)
{
printf("没有找到数。\n");
}
else
{
q->next = p->next;
free(p);
}
}
}

void link_reverse(Link head)  //反转链表
{
Link p1,p2,p3,q;
p1 = p2 = p3 = head->next;

if(p1 == NULL)
{
printf("Link is empty!\n");
return;
}
else if(p1->next == NULL)
{
return;
}
else
{
p2 = p1->next;
if(p2->next == NULL)
{
p2->next = p1;
p1->next = NULL;
head->next = p2;
}
else
{
p3 = p2->next;
while(p3->next != NULL)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
p3->next = p2;
q = head->next;
q->next = NULL;
head->next = p3;
}
}

}

int main()
{
Link head = NULL;
Link new_node = NULL;
int i;
int num_val,num_loc;

create_link(&head);

for(i = 0; i < 10; i++)
{
create_node(&new_node,i);
insert_node_head(head,new_node);
}

display(head);

printf("请输入要插入的位置。\n");
scanf("%d",&num_loc);
printf("请输入要插入的数。\n");
scanf("%d",&num_val);

create_node(&new_node,num_val);

insert_node_mid(head,new_node,num_loc);
display(head);

printf("请输入要删除的数。\n");
scanf("%d",&num_val);
node_del(head,num_val);
display(head);

printf("*********\n");
link_reverse(head);
display(head);

return 0;
}


循环链表
创建+头插+尾插+中间插入+删除+反序+释放内存
#include <stdio.h>
#include <stdlib.h>

#define MAL_OK 1
#define MAL_ERR 0

struct node
{
int num;
struct node * next;
};

typedef struct node Node;
typedef struct node * Link;

int malloc_ok(Link new_node)  //判断空间是否创建成功
{
if(new_node == NULL)
{
return MAL_ERR;
}
else
{
return MAL_OK;
}
}

void create_node(Link * new_node, int i)  //创建空间
{
(*new_node) = (Link)malloc(sizeof(Node));
while(malloc_ok(*new_node) == MAL_ERR)
{
(*new_node) = (Link)malloc(sizeof(Node));
}
(*new_node)->num = i;
}

void create_link(Link * head)  //创建带表头结点的链表
{
create_node(head,0);
(*head)->next = *head;
}

void insert_node_head(Link head,Link new_node)  //头插
{
new_node->next = head->next;
head->next = new_node;
}

void insert_node_tail(Link head,Link new_node)  //尾插
{
Link p;
p = head;
while(p->next != head)
{
p = p->next;
}
p->next = new_node;
new_node->next = head;
}

void insert_node_mid(Link head,Link new_node,int num_loc)  //中间插入
{
Link p,q;
q = head;
p = head->next;

if(p == head)
{
head->next = new_node;
new_node->next = head;
}
else
{
while(p->num != num_loc && p->next != head)
{
q = p;
p = p->next;
}
if(p->next == head && p->num != num_loc)
{
p->next = new_node;
new_node->next = head;
}
else
{
q->next = new_node;
new_node->next = p;
}
}

}

void display(Link head)
{
Link p;
p = head;

if(p == NULL)
{
printf("no Link.\n");
}
else if(p->next == head)
{
printf("Link is empty.\n");

}
else
{
while(p->next != head)
{
p = p->next;
printf("num = %d\n",p->num);
}
}
}

void node_del(Link head,int num_val)  //删除一个数
{
Link p,q;
q = head;
p = head->next;

if(p == head)
{
printf("链表为空。\n");
}
else
{
while(p->num != num_val && p->next != head)
{
q = p;
p = p->next;
}
if(p->next == head && p->num != num_val)
{
printf("没有找到数。\n");
}
else
{
q->next = p->next;
free(p);
}
}
}

void release_link(Link * head)  //释放内存以免内存泄漏
{
Link p;
p = (*head)->next;
if(p == *head)
{
printf("link is empty.\n");
free(p);
*head = NULL;
}
else
{
while(p != *head)
{
(*head)->next = p->next;
free(p);
p = (*head)->next;
}
free(*head);
*head = NULL;
}
}

void link_recerse(Link head)  //反转链表
{
Link p1,p2,p3,q;
p1 = p2 = p3 = head->next;

if(p1 == head)
{
printf("Link is empty.\n");
return;
}
else if(p1->next == NULL)
{
return;
}
else if(p1->next == head)
{
return;
}
else
{
p2 = p1->next;
if(p2->next == NULL)
{
p2->next = p1;
p1->next = head;
head->next = p2;
}
else
{
p3 = p2->next;
while(p3->next != head)
{
p2->next = p1;
p1 = p2;
p2 = p3;
p3 = p3->next;
}
p2->next = p1;
p3->next = p2;
q = head->next;
q->next = head;
head->next = p3;
}
}
}

int main()
{
Link head = NULL;
Link new_node = NULL;
int i;
int num_val,num_loc;
create_link(&head);

for(i = 0; i < 10; i++)
{
create_node(&new_node,i);
insert_node_tail(head,new_node);
}

display(head);

printf("请输入要插入的位置。\n");
scanf("%d",&num_loc);
printf("请输入要插入的数。\n");
scanf("%d",&num_val);
create_node(&new_node,num_val);
insert_node_mid(head,new_node,num_loc);
display(head);

printf("请输入要删除的数字。\n");
scanf("%d",&num_val);
node_del(head,num_val);
display(head);

release_link(&head);
display(head);

return 0;
}




展开全文
• 1.建立一个如图所示的简单链表，它由三个学生数据的结点组成 2.添加结点到链表首 3.添加结点到链表尾 4.从链表首结点开始释放内存 5.从链表尾结点开始释放内存
1.建立一个如图所示的简单链表，它由三个学生数据的结点组成

代码：

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct student
{
int num;//学号
char name[20];//姓名
double score;//成绩
struct student *next;//下一个结点地址
};
int main()
{
struct student *a,*b,*c,*head=NULL;
//建立四个结构体指针，其中head用来保存链表首地址，初始的NULL值表示还是一个空链表
a=malloc(sizeof(struct student));
//动态分配连续内存空间，长度为sizeof(struct student)，并把起始地址赋给a
a->num=110011;
strcpy(a->name,"张三");
a->score=88.5;
b=malloc(sizeof(struct student));
b->num=110012;
strcpy(b->name,"李四");
b->score=90.2;
c=malloc(sizeof(struct student));
c->num=110013;
strcpy(c->name,"王五");
c->score=77.0;//创建链表的三个结点，并把地址保存到a,b,c变量中
head=a;//将结点a的起始地址赋给头指针head,head开始的链表就有了一个结点
a->next=b;//将b中地址保存到a->next中,head开始的链表中就有了两个结点
b->next=c;//将c中地址保存到b->next中,head开始的链表中就有了三个结点
c->next=NULL;//将NULL保存到c->next中,完成链表结尾
free(a);
free(b);
free(c);//释放内存
return 0;
}

创建链表最基本的方法是没创建一个结点，就把它添加到链表中，然后用循环重复这个过程，直到链表创建完成。
在创建链表的每次循环中，都要添加一个结点到链表中，这个结点可以添加到链表末尾，也可以添加到链表的起始位置。

2.添加结点到链表首
添加结点到链表首是创建链表最简单的方法，其步骤如下：
创建新结点。使原来链表首结点的地址成为先结点的下一个结点。使链表头地址即head指向本结点。重复步骤1~3的过程。例.读入一组整型数据，该组数据以-1代表结束。

代码：

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct SNode
{
int num;//学号
struct SNode *next;//下一个节点地址
};
int main()
{
struct SNode *p,*head=NULL;//head用来保存链表首地址,初始值NULL表示这是一个空链表
do
{
p=malloc(sizeof(struct SNode));
scanf("%d",&p->num);
p->next=head;
head=p;
}
while(p->num!=-1);
return 0;
}循环说明：

程序第一次进入#12~#19行的循环，则:
#14行创建一个结点，并让p指向该结点。
#15行读入整数到p指向的结点。
#16行把head的值保存到p->next中。
#17行把p的值赋给head,head指向的链表有了一个结点。
#19行判断p->num不是-1，所以进入下一次循环。。。。。。

3.添加结点到链表尾
添加结点到链表尾，需要两个指针分别指向链表的首尾结点，其步骤如下：

（1）创建新结点，并把新结点的next指针赋值为NULL。（2）判断当前链表是否为空链表。如果是，则把链表首、末结点指针都指向新结点。

如果否，则把链表末节点的指针指向新结点。

（3）重复步骤1~2过程。
例.读入一组整型数据，该组数据以-1代表结束。
代码：
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct SNode
{
int num;//学号
struct SNode *next;//下一个节点地址
};
int main()
{
struct SNode *p,*head=NULL,*tail=NULL;
//head保存链表首结点地址，tail保存链表末结点地址，NULL代表这还是一个空链表
do
{
p=malloc(sizeof(struct SNode));
scanf("%d",&p->num);
p->next=NULL;
//创建一个结点，并让p指向这个结点，读入整数到这个结点，并使它的next指针值为NULL
if(head==NULL){
head=p;
tail=p;
}
else{
tail->next=p;
tail=tail->next;
}
}
while(p->num!=-1);
return 0;
}
循环说明：
程序第一次进入#13~#28行的循环：
#19行中因为head值为NULL，所以执行#20~#21行，对head、tail赋值。
#28行判断p->num不是-1，所以程序进入下一次循环。
程序第二次进入#13~#28行的循环：
#19行中因为head值不为NULL，所以执行#24行，将新结点连接到链表末尾
#25行将新结点的地址赋值给tail，使tail指向新的链表末尾结点
#28行判断p->num不是-1，所以程序进入下一循环......

链表中使用的内存是由用户动态申请分配的，所以应该在链表使用完后，主动把这些内存交还给系统。链表释放占用的内存要考虑链表对内存的使用方式。

4.从链表首结点开始释放内存
通过链表头指针head可以找到链表首结点，因为链表的第二个结点的地址保存在首结点的next指针中，所以在释放首结点前要把这个值保存下来，否则释放首结点后，链表的第二个结点就找不到了。算法如下：
（1）将链表第二个结点设为新首结点
（2）释放原来的首结点
（3）重复步骤（1）~（2）
例.编写一个函数，释放如图所示head指向的链表。

代码：
void freelink(struct SNode *head)
{
struct SNode *p;
while(head)
{
p=head;
head=head->next;
free(p);
}
}说明：

#4行首先判断head是否为NULL，不为NULL说明链表还有结点， 执行#5~#9行的循环，
#6行链表首结点赋值给指针变量p，
#7行把链表第二个结点的地址赋值给head，
#8行释放p指向的结点；
#4行判断head是否为NULL，不为NULL说明链表还有结点，第二次执行#5~#9行循环......

5.从链表尾结点开始释放内存
如果要从链表尾结点开始释放内存，因为程序只保存链表首结点的地址，所以需要从首结点沿着每个结点的next指针找到尾结点，才能释放该尾结点。释放完尾结点还有一个工作要做，就是把新的尾节点的next指针赋值为NULL。算法如下：
（1）找到链表的尾结点
（2）将尾结点的前一个结点设成新的尾结点
（3）释放旧的尾结点
（4）重复步骤（1）~（3）。
以上算法比较复杂，如果使用递归要简单一些，使用递归算法如下：
（1）如果当前结点是链表最末节点，则释放当前结点，把指向当前结点中的链表中的指针（head指针或上一结点的next指针）赋值为NULL
（2）如果当前结点不是最末结点，则释放当前结点后面的链表，在、再释放当前结点，把指向当前结点的链表中的指针（head指针或上一结点的next指针）赋值为NULL。

例.编写一个函数，用递归的方法释放head指向开始结点的链表。
代码：void freelink(struct SNode **p)
{
if((*p)->next==NULL){
free(*p);
*p=NULL;
}
else{
freelink(&(*p)->next);
free(*p);
*p=NULL;
}
}说明：如果链表的首地址是head，则该函数的调用方法是freelink（&head），不能用空链表调用该函数，即head值不能为NULL。


展开全文
• Description 编写一个函数creatlink，用来建立一个动态链表。（包含学号和成绩） 编写一个函数printlink，用来输出一个链表。 编写一个函数dellink，用来删除动态...编写一个函数freelink，用来释放一个动态链表。 In
Description

编写一个函数creatlink，用来建立一个动态链表。（包含学号和成绩）
编写一个函数printlink，用来输出一个链表。
编写一个函数dellink，用来删除动态链表中一个指定的结点(由实参指定某一学号，表示要删除该学生结点)。
编写一个函数insertlink，用来向动态链表插入一个结点。
编写一个函数freelink，用来释放一个动态链表。

Input

输入多个学生的学号和成绩，建立动态链表，以0 0 结束
输入学号，删除链表中的对应结点
插入两个链表结点

Output

输出的链表
#include<iostream>
#include<iomanip>
using namespace std;
/********************************************************/
struct student
{
long num;
float score;
student *next;
};
/********************************************************/
student *creatlink(void)//建立链表
{
student *st=new student,*pend,*head;//申请内存空间
cin>>st->num>>st->score;//输入学生信息
head=NULL;
while(st->num!=0)//当输入0 0时结束
{
if(head==NULL)
head=st;//head起个头
else
pend->next=st;//指向下一个结点的地址
pend=st;
st=new student;//重新申请内存地址
cin>>st->num>>st->score;
}
pend->next=NULL;
delete st;//把多申请的那个释放
return head;//返回首地址，千万别改
}
/********************************************************/
void printlink(student *head)//链表输出
{
while(head!=NULL)
{
cout<<head->num<<" "<<head->score<<endl;
head=head->next;
}
}
/********************************************************/
student *dellink(student *head,long del)//删除
{
student *p1,*p2=head;
while(p2!=NULL)
{

if(del==p2->num)
{
p1->next=p2->next;
//上一个的next指向被删除结点的下一个地址
//也就是上一个的next的值换成下一个next的值
break;
}
else
{
p1=p2;
p2=p2->next;
}
}
return head;
}
/********************************************************/
student *insertlink(student *head,student *std)//插入
{
student *p2=head,*p1,*st=new student;//一定要申请新的内存地址
st->num=std->num;//把值赋给st就可以了，别赋地址
st->score=std->score;
st->next=std->next;
while(p2->next!=NULL)
{
if(p2->num<st->num&&st->num<p2->next->num)
//简单的排一下序
{
p1=p2->next;
p2->next=st;
st->next=p1;
return head;
//插进去了就退出吧
}
else
p2=p2->next;
}
if(p2->next==NULL)//当在最后插入结点时
{
p2->next=st;
st->next=NULL;//别忘了
}
return head;
}
/********************************************************/
void freelink(student *head)//释放链表
{
student *p1=head,*p2;
while(p1!=NULL)//排着释放
{
p2=p1->next;
delete p1;
p1=p2;
}
}
/********************************************************/
int main()
{
student *creatlink(void);
student *dellink(student *,long);
student *insertlink(student *,student *);
void printlink(student *);
void freelink(student *);
student *head,stu;
long del_num;
head=creatlink();
cin>>del_num;
head=dellink(head,del_num);
cin>>stu.num>>stu.score;
head=insertlink(head,&stu);
cin>>stu.num>>stu.score;
head=insertlink(head,&stu);
cout<<setiosflags(ios::fixed);
cout<<setprecision(2);
printlink(head);
freelink(head);
return 0;
}
/*
Sample Input
1001 100
1002 95
1005 90
1008 76
0 0
1005
1006 98
1009 99
Sample Output
1001 100.00
1002 95.00
1006 98.00
1008 76.00
1009 99.00
*/



展开全文
• 以后，要注意clear_foo() 释放内存空间，最好的办法是在该链表类的析构方法中执行 this->clear_foo(); Repeated Embedded Message Fields Given the message type: message Bar {} For this field def

在使用 Repeated 类型 链表结构 使用add_foo()
以后，要注意clear_foo() 释放内存空间，最好的办法是在该链表类的析构方法中执行 this->clear_foo();

Repeated Embedded Message Fields

Given the message type:
message Bar {}

For this field definitions:
repeated Bar foo = 1;

The compiler will generate the following accessor methods:

int
foo_size() const: Returns the number of elements currently in the field.
const
Bar& foo(int index) const: Returns the element at the given zero-based index.
Bar*
mutable_foo(int index): Returns a mutable pointer to the Bar object
that stores the value of the element at the given zero-based index. The pointer is invalidated by a call to Clear() or clear_foo(),
or by manipulating the underlying RepeatedPtrField in
a way that would remove this element.
Bar*
add_foo(): Adds a new element and returns a pointer to it. The returned Bar will
have none of its fields set (i.e. it will be identical to a newly-allocated Bar).
The pointer is invalidated by a call to Clear() or clear_foo(),
or by manipulating the underlying RepeatedPtrField in
a way that would remove this element.
void
clear_foo(): Removes all elements from the field. After calling this, foo_size() will
return zero.
const RepeatedPtrField<Bar>&
foo() const: Returns the underlying RepeatedPtrField that
stores the field's elements. This container class provides STL-like iterators and other methods.
RepeatedPtrField<Bar>* mutable_foo():
Returns a mutable pointer to the underlying RepeatedPtrField that
stores the field's elements. This container class provides STL-like iterators and other methods.
展开全文
• 链表的一些操作 作为一个刚刚进入大学的萌新，从开学到现在（已经期末了），一直都是在看别人写的博客，终于有一天可以试着写自己的博客了，好了话不多说，开始进入正题 这周C语言的课刚刚教了链表，我就对这神奇的...
• 对于free()释放空间有个疑问：指针p和指针q同时指向一条链表h，即p=q=h，这时free(p)，整条链被释放了吗？目前我的认识水平是这样的，free(p)后，就是告诉系统p所在的空间释放了，系统可以再次利用这部分空间，...
• C语言实现删除链表所有节点空间 节点结构 struct node ...//释放链表节点空间 void delete_chain(node *head) { node *p1; while (head) { p1 = head; head = head->next; free(p1); } }
• ## 链表

2019-09-05 17:24:59
链表删除结点后，如何释放空间空间该如何处理
• ## 链表内存的释放

千次阅读 2007-11-22 20:22:00
链表是一种很常用的数据结构，如果在建立的时候为其每个节点分配了堆中的内存，则在程序结束前应该释放它，下面是常有的一段释放链表内存的程序：p = plist;//p和plist是指向一段相同地址空间的两个不同指针。...
• 1.动态链表的创建和内存申请： typedef struct _STACK{  void* data;  int size;  struct _STACK* next;  struct _STACK* pre; } STACK; STACK *stack; STACK *_stack; void initStack() ｛ stack = (S
• 标题：动态空间 ,简单链表 关键词：动态空间100%，简单链表50% 内容（A）动态空间释放： （1）在C++中用new分配动态内存不会自动释放，必须用delete运算符释放。 delete运算符释放动态内存的一般格式： ...
• 众所周知，链表结构相对于数组结构的一个优秀之处在于其删除元素操作仅靠更改指针指向即可完成，而数组则需要移动元素。但链表中被删除的元素所占用的资源是否需要被释放
• 同遍历链表类似，区别在于p_mov每指向某个节点后都将该节点释放 1、释放前要先保存下一个节点，释放后备份恢复给p_mov,否则释放了当前节点，下一个节点的地址就将失去； 2、依次将所有节点释放后，最后返回NULL...
• 2、在空间的利用上链表相比数组要更加灵活，不会造成内存的大量浪费。 3、向链表中插入或从链表中删除一项的操作不需要移动很多项，只涉及常数个节点链的改变，时间复杂度为O（1）。 缺点： 由于在链表中，仅仅只有...
• 要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中允许有重复的数据 由于最近数据结构课布置了这个作业，并且知识一知半解（练习少了），所以百度找了一些代码看，然后搞了七八个小时弄...
• 要求结果链表仍使用原来两个链表的存储空间，不另外占用其他的存储空间。表中允许有重复的数据。 void MergeList(LinkList& La, LinkList& Lb, LinkList& Lc, ) { //合并链表La和Lb，合并后的新表使用...
• // 释放链表 void Free_list(List *head){  List *freeNode;  while (NULL != head){  freeNode = head;  head = head -> next;  free(freeNode);  }  return; } int main(void) {  int...
• 要求结果链表仍使用原来两个链表的存储空间, 不另外占用其它的存储空间。表中不允许有重复的数据。 [题目分析] 合并后的新表使用头指针Lc指向，pa和pb分别是链表La和Lb的工作指针,初始化为相应链表的第一个结点，从...
• 链表释放 FreeList 链表的插入 InsertNode 链表的删除 DeleteNode 附加一个打印 DisPlay 功能都封装在函数里且注释清楚，有需要直接转接口或者调用即可。 #include<stdio.h> typedef struct tagNode { ...
• ## C语言链表操作详解

万次阅读 多人点赞 2018-12-29 19:01:55
为什么要使用链表 在未学习链表时，我们常用的存储数据的方式无非就是数组。使用数组存储数据的好处就是查询快，但是它的弊端也很明显： 使用前需声明数组的长度，一旦声明长度就不能更改 插入和删除操作需要...
• 第二部分：针对链表节点重载operator new 和operator delete 实现链表节点使用内存池申请和释放空间 # include # include using namespace std ; struct ListNode { ListNode * _prev ; ...
• 已知二叉树以二叉链表存储，编写算法完成：对于树中每个元素值为x的结点，删去以它为根的子树，并释放相应的空间，感觉课后习题答案跟我的差别太大，于是拿出电脑上机运行一下，结果很满意！

...