1.哈夫曼树和哈夫曼编码
1.思路理解 代码还没有理解
# include <stdio.h>
# define MAX 100
typedef struct
{
int weight;
int lchild, rchild, parent;
}HFMT;
//哈夫曼树的初始化
void InitHFMT (HFMT HF[MAX], int n)
{
int i;
//下面的for循环是给每个结点初始化
for (i = 0; i < 2*n-1; i++)
{
HF[i].weight = 0;
HF[i].lchild = -1;
HF[i].rchild = -1;
HF[i].parent = -1;
}
//下面的for循环给叶子结点的weight域赋初值
for (i = 0; i < n; i++)
{
printf ("请输入第%d个结点的权值:",i+1);
scanf ("%d", &HF[i].weight);
getchar ();
//吸收回车键
}
}
//找到权值最小的两个节点
void Min (HFMT HF[MAX], int n, int* p, int* r, int j)
{
int Min1 = 9999;
int Min2 = 9999;
int i;
//下面的for循环是为了找到最小的权值所对应的数组下标
for (i = 0; i < j; i++)
{
if (HF[i].parent == -1 && HF[i].weight < Min1)
//HF[i].parent == -1表示未加入哈夫曼树
{
Min1 = HF[i].weight;
*p = i;
}
}
//下面的for循环是为了找到次最小的权值所对应的数组下标
for (i = 0; i < j; i++)
{
if (HF[i].parent == -1 && HF[i].weight < Min2 && HF[i].weight > Min1)
{
Min2 = HF[i].weight;
*r = i;
}
}
}
//哈夫曼树的创建
void CreateHFMT (HFMT HF[MAX], int n)
{
int p, r;
int i, k;
InitHFMT (HF, n);
for (i = n; i < 2*n -1; i++)
{
Min (HF, n, &p, &r, i);
HF[p].parent = i;
HF[r].parent = i;
HF[i].lchild = HF[p].weight;
HF[i].rchild = HF[r].weight;
HF[i].weight = HF[i].lchild + HF[i].rchild;
}
}
void HFnode (HFMT HF[MAX], int i, int j)
{
j = HF[i].parent;
if (HF[j].rchild == HF[i].weight)
//如果它在父母结点的右边
{
printf ("1");
}
else
//如果在左边
{
printf ("0");
}
if (HF[j].parent != -1)
//如果它还有父母结点
{
i = j;
HFnode (HF, i, j);
}
}
void HFMTnode (HFMT HF[MAX], int n)
{
int a, i, j = 0;
printf ("\n输入的权值所对应的哈夫曼代码为:\n");
for (i = 0; i < n; i++)
{
a = i;
printf ("%d的编码为:", HF[i].weight);
HFnode (HF, i, j);
printf ("\n");
i = a;
}
}
int main (void)
{
int n;
HFMT HF[MAX];
printf ("请输入权值的个数:");
scanf ("%d", &n);
CreateHFMT (HF, n);
HFMTnode (HF, n);
return 0;
}
# include <stdio.h>
# define MAX 100
typedef struct
{
int weight;
int lchild, rchild, parent;
}HFMT;
//哈夫曼树的初始化
void InitHFMT (HFMT HF[MAX], int n)
{
int i;
//下面的for循环是给每个结点初始化
for (i = 0; i < 2*n-1; i++)
{
HF[i].weight = 0;
HF[i].lchild = -1;
HF[i].rchild = -1;
HF[i].parent = -1;
}
//下面的for循环给叶子结点的weight域赋初值
for (i = 0; i < n; i++)
{
printf ("请输入第%d个结点的权值:",i+1);
scanf ("%d", &HF[i].weight);
getchar ();
//吸收回车键
}
}
//找到权值最小的两个节点
void Min (HFMT HF[MAX], int n, int* p, int* r, int j)
{
int Min1 = 9999;
int Min2 = 9999;
int i;
//下面的for循环是为了找到最小的权值所对应的数组下标
for (i = 0; i < j; i++)
{
if (HF[i].parent == -1 && HF[i].weight < Min1)
//HF[i].parent == -1表示未加入哈夫曼树
{
Min1 = HF[i].weight;
*p = i;
}
}
//下面的for循环是为了找到次最小的权值所对应的数组下标
for (i = 0; i < j; i++)
{
if (HF[i].parent == -1 && HF[i].weight < Min2 && HF[i].weight > Min1)
{
Min2 = HF[i].weight;
*r = i;
}
}
}
//哈夫曼树的创建
void CreateHFMT (HFMT HF[MAX], int n)
{
int p, r;
int i, k;
InitHFMT (HF, n);
for (i = n; i < 2*n -1; i++)
{
Min (HF, n, &p, &r, i);
HF[p].parent = i;
HF[r].parent = i;
HF[i].lchild = HF[p].weight;
HF[i].rchild = HF[r].weight;
HF[i].weight = HF[i].lchild + HF[i].rchild;
}
}
void DisHFMT (HFMT HF[MAX], int n)
{
int i;
printf ("\n哈夫曼树的各边显示:\n");
for (i = 0; i < 2*n-1; i++)
{
if (HF[i].lchild != -1)
{
printf ("(%d, %d), (%d, %d)\n", HF[i].weight, HF[i].lchild, HF[i].weight, HF[i].rchild);
}
}
}
int main (void)
{
int n;
HFMT HF[MAX];
printf ("请输入权值的个数:");
scanf ("%d", &n);
CreateHFMT (HF, n);
DisHFMT (HF, n);
return 0;
}
2.排序
1.插入排序
时间复杂度:最坏情况下为O(N*N)
最好情况下为O(N)
空间复杂度:O(1)
#include<iostream>
using namespace std;
int a[10000+7];
void InsertSort(int *arr,int n){
for(int i=0;i<n-1;i++){//注意n-1
int end=i;
int tem=arr[end+1];//所选元素以后的目标元素
while(end>=0){
if(tem<a[end]){
a[end+1]=a[end];
end--;
}
else break;
}
arr[end+1]=tem;//因为end--
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
InsertSort(a,n);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
2.希尔排序
1.增量,每次除二向下取整,以一为结束
2.时间复杂度平均:O(N^1.3)
空间复杂度:O(1)
#include<iostream>
using namespace std;
int a[10000+7];
void ShellSort(int*arr,int n){
int gap=n;
while(gap>1){//最后是两两交换
gap=gap/2;
for(int i=0;i<n-gap;i++){// 注意n-nap
int end=i;
int tem=arr[end+gap];
while(end>=0){//end一定大于0
if(tem<arr[end]){
arr[end+gap]=arr[end];
end-=gap;//就是end-=gap 同一个位置的数据不仅仅处理一次
}
else break;
}
arr[end+gap]=tem;
}
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
ShellSort(a,n);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
3.选择排序
1.时间复杂度:最坏情况:O(N^2)
最好情况:O(N^2)
空间复杂度:O(1)
2.选出最大最小,不断缩短区间
#include<iostream>
using namespace std;
int a[10000+7];
void swap(int *a,int *b){
int tem=*a;
*a=*b;
*b=tem;
}
void SelectSort(int *arr,int n){
int begin=0,end=n-1;
while(begin<end){
int maxi=begin;
int mini=begin;
for(int i=begin;i<=end;i++){
if(arr[i]<arr[mini]){//找到最小
mini=i;
}
if(arr[i]>arr[maxi]){//找到最大
maxi=i;
}
}
swap(&arr[mini],&arr[begin]);
//防止最大的数在begin位置被换走(暂时不理解)
if(begin==maxi){
maxi=mini;
}
swap(&arr[maxi], &arr[end]);
++begin;//两边向中间靠拢
--end;
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
SelectSort(a,n);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
4.冒泡排序
1.时间复杂度:最坏情况:O(N^2)
最好情况:O(N)
空间复杂度:O(1)
#include<iostream>
using namespace std;
int a[10000+7];
void BubbleSort(int *arr,int n){
int end=n;
while(end){
int flag=0;
for(int i=1;i<end;i++){
if(arr[i-1]>arr[i]){//从头开始,每次进行交换,把更大的换上去
int tem=arr[i];
arr[i]=arr[i-1];
arr[i-1]=tem;
flag=1;
}
}
if(flag==0)break;//没有更大的了
end--;
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
BubbleSort(a,n);
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
5.归并排序
1.速度仅次于快速排序。
2.
时间
O(nlogn)。
空间
O(N),归并排序需要一个与原数组相同长度的数组做辅助来排序。
#include<iostream>
using namespace std;
int a[1000+7];
int b[1000+7];
void Merge(int sourceArr[],int tempArr[], int startIndex, int midIndex, int endIndex){
int i = startIndex, j=midIndex+1, k = startIndex;
while(i!=midIndex+1 && j!=endIndex+1) {
if(sourceArr[i] > sourceArr[j])
tempArr[k++] = sourceArr[j++];
else
tempArr[k++] = sourceArr[i++];
}
while(i != midIndex+1)//可能有些数据没有处理完全
tempArr[k++] = sourceArr[i++];
while(j != endIndex+1)
tempArr[k++] = sourceArr[j++];
for(i=startIndex; i<=endIndex; i++)
sourceArr[i] = tempArr[i];
}
void MergeSort(int sourceArr[], int tempArr[], int startIndex, int endIndex) {
int midIndex;
if(startIndex < endIndex) {
midIndex = startIndex + (endIndex-startIndex) / 2;//避免溢出int 等价于>>1
MergeSort(sourceArr, tempArr, startIndex, midIndex);//开始递归细分,以二为节点
MergeSort(sourceArr, tempArr, midIndex+1, endIndex);
Merge(sourceArr, tempArr, startIndex, midIndex, endIndex);
}
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
MergeSort(a,b,0,n-1);//注意 endidx传的是最后一个元素的位置
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
6.快速排序
#include<iostream>
using namespace std;
int a[1000+7];
int b[1000+7];
void QuickSort(int *arr,int begin,int end){
if(begin>=end)return;//边界判断
int left = begin,right = end;
int key = arr[begin];//目标key位置固定 左边小 右边大
while(begin<end){
while(arr[end]>=key&&begin<end){
end--;
}
arr[begin]=arr[end];
while(arr[begin]<=key&&begin<end){
begin++;
}
arr[end]=arr[begin];
}
arr[begin] = key;
int keyi = begin;
//[left,keyi-1]keyi[keyi+1,right]
QuickSort(arr, left, keyi - 1);
QuickSort(arr, keyi + 1, right);
}
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
QuickSort(a,0,n-1);//注意 endidx传的是最后一个元素的位置
for(int i=0;i<n;i++){
cout<<a[i]<<" ";
}
return 0;
}
3.栈
(优点:简洁且节省空间)
基本操作
- InitStack(&S)初始化一个空栈
- StackEmpty(S)判断栈S是否为空
- Push(&S,x)进栈
- Pop(&S,&x)出栈
- GetTop(S,&x)读取栈顶元素
- DestroyStack(&S)销毁栈,释放其空间
- 顺序栈
- 思路:利用一组地址连续的存储单元存放底部到顶部的所有数据,同时利用一个指针指示栈顶元素。
- 初始化
void InitStack(SqStack& S) {
S.top = -1;
}
2)判断栈是否为空
bool StackEmpty(SqStack S) {
if (S.top == -1) return true;
else return false;
3)进栈(先让指针加1,再将x入栈)
bool Push(SqStack& S, ElemType x) {
if (S.top == MaxSize - 1) return false;
S.data[++S.top] = x;
return true;
}
}
4)出栈
bool Pop(SqStack& S, ElemType& x) {
if (S.top == -1) return false;
x = S.data[S.top--];
return true;
}
5)读取顶部元素
bool GetTop(SqStack S, ElemType& x) {
if (S.top == -1) return false;
x = S.data[S.top];
return true;
}
整体代码实现:
#include<iostream>
#include<algorithm>
#define MaxSize 50
#define ElemType int
using namespace std;
typedef struct {
ElemType data[MaxSize];
int top;
}SqStack;
int x;
void InitStack(SqStack& S) {
S.top = -1;
}
bool StackEmpty(SqStack S) {
if (S.top == -1) return true;
else return false;
}
bool Push(SqStack& S, ElemType x) {
if (S.top == MaxSize - 1) return false;
S.data[++S.top] = x;
return true;
}
bool Pop(SqStack& S, ElemType& x) {
if (S.top == -1) return false;
x = S.data[S.top--];
return true;
}
bool GetTop(SqStack S, ElemType& x) {
if (S.top == -1) return false;
x = S.data[S.top];
return true;
}
int main() {
SqStack S;
InitStack(S);
Push(S, 0);
Push(S, 1);
Push(S, 2);
Push(S, 3);
Push(S, 4);
while (!StackEmpty(S)) {
GetTop(S, x);
cout << x << endl;
Pop(S, x);
}
return 0;
}
运行结果
共享栈(可以减少空间的使用)
Top0与Top1相遇时,则栈满0号进栈时,top0先加1,再入栈而1号栈时,top1先减1,再入栈,两边操作是相反的
- 链式存储
定义变量
typedef struct LinkNode {
int data;
struct LinkNode* next;
}stackNode, * LinkStack;
1)初始化
void initStack(LinkStack& s)
{
s = NULL.
}
2)判空
bool stackEmpty(LinkStack s)
{
if (s == NULL)
return true;
return false;
}
3)求长度
int stackLength(LinkStack s)
{
int sum = 0;
stackNode* temp = s;
while (temp != NULL)
{
sum++;
temp = temp->next;
}
return sum;
}
4)入栈
void push(LinkStack& s, int e)
{
stackNode* p = new stackNode;
p->data = e;
p->next = NULL;
if (s == NULL)
s = p;
else
{
p->next = s;
s = p;
}
}
5)出栈
void pop(LinkStack& s, int& e)
{
stackNode* p = new stackNode;
if (s == NULL)
{
cout << "栈为空,无法弹出" << endl;
}
else
{
p = s;
e = p->data;
s = s->next;
delete p;
cout << "成功弹出栈顶元素" << endl;
}
}
6)读取栈顶元素
int top(LinkStack s)
{
if (s == NULL)
return -1;
return s->data;
}
7)摧毁栈
void DestoryStack(LinkStack& S)
{
stackNode* p;
while (S)
{
p = S;
S = S->next;
delete p;
}
S = NULL;
cout << "成功销毁" << endl;
}
总体代码
#include <iostream>
using namespace std;
typedef struct LinkNode {
int data;
struct LinkNode* next;
}stackNode, * LinkStack;
void initStack(LinkStack& s)
{
s = NULL;
}
bool stackEmpty(LinkStack s)
{
if (s == NULL)
return true;
return false;
}
int stackLength(LinkStack s)
{
int sum = 0;
stackNode* temp = s;
while (temp != NULL)
{
sum++;
temp = temp->next;
}
return sum;
}
void push(LinkStack& s, int e)
{
stackNode* p = new stackNode;
p->data = e;
p->next = NULL;
if (s == NULL)
s = p;
else
{
p->next = s;
s = p;
}
}
void pop(LinkStack& s, int& e)
{
stackNode* p = new stackNode;
if (s == NULL)
{
cout << "栈为空,无法弹出" << endl;
}
else
{
p = s;
e = p->data;
s = s->next;
delete p;
cout << "成功弹出栈顶元素" << endl;
}
}
int top(LinkStack s)
{
if (s == NULL)
return -1;
return s->data;
}
//销毁栈
//所有节点
void DestoryStack(LinkStack& S)
{
stackNode* p;
while (S)
{
p = S;
S = S->next;
delete p;
}
S = NULL;
cout << "成功销毁" << endl;
}
void menu()
{
cout << "**************************" << endl;
cout << "1.初始化" << endl;
cout << "2.判断栈是否为空" << endl;
cout << "3.求栈的长度" << endl;
cout << "4.销毁栈" << endl;
cout << "5.入栈" << endl;
cout << "6.出栈" << endl;
cout << "7.求栈顶元素" << endl;
cout << "8.退出" << endl;
cout << "**************************" << endl;
}
int main()
{
int choice;
LinkStack s;
int e1, e2;
while (1)
{
menu();
cin >> choice;
switch (choice)
{
case 1:
initStack(s);
cout << "初始化成功" << endl;
break;
case 2:
if (stackEmpty(s))
cout << "栈为空" << endl;
else
cout << "栈不为空" << endl;
break;
case 3:
cout << "栈的长度为" << stackLength(s) << endl;
break;
case 4:
DestoryStack(s);
break;
case 5:
cout << "请输入想要入栈的元素值:" << endl;
cin >> e1;
push(s, e1);
cout << "入栈成功" << endl;
break;
case 6:
pop(s, e2);
cout << "弹出的元素为" << e2 << endl;
break;
case 7:
if (top(s) )
cout << "栈顶元素为" << top(s) << endl;
else
cout << "栈为空" << endl;
break;
case 8:
cout << "成功退出" << endl;
exit(0);
default:
cout << "输入有误,请重新输入" << endl;
break;
}
}
}
运行结果
#include<iostream>
using namespace std;
typedef struct LinkNode{
int data;
struct LinkNode*next;
}stackNode,*LinkStack;
void Init(LinkStack& s){
s=NULL;
}
bool stackEmpty(LinkStack s){
if(s==NULL)return true;
return false;
}
int stackLength(LinkStack s){
int sum=0;
stackNode*temp=s;
while(temp!=NULL){
sum++;
temp=temp->next;
}
return sum;
}
void push(LinkStack &s,int e){
stackNode*p=new stackNode;
p->data=e;
p->next=NULL;
if(s==NULL)s=p;
else{
p->next=s;
s=p;
}
}
void pop(LinkStack&s,int &e){
stackNode*p=new stackNode;
if(s==NULL)cout<<"error"<<endl;
else{
p=s;
e=p->data;
s=s->next;
delete p;
cout<<"OK"<<endl;
}
}
int top(LinkStack s){
if(s==NULL)return -1;
return s->data;
}
void DestoryStack(LinkStack&s){
stackNode*p;
while (s){
p=s;
s=s->next;
delete p;
}
s=NULL;
cout<<"OK"<<endl;
}
int main(){
LinkStack s;
Init(s);
int e1,e2;
if(stackEmpty(s))cout<<"empty"<<endl;
else cout<<"not empty"<<endl;
for(int i=0;i<3;i++){
cin>>e1;
push(s,e1);
}
for(int i=0;i<3;i++){
\
pop(s,e2);
cout<<e2<<endl;
}
return 0;
}
4.链表
链表
- 单向链表
- 包括两部分:数据域和指针域
Typedef struct student {
Int num;//数据域 存放本节点的数据
Struct student *next;//指针域 存放下一个节点的首地址
}STU;
- 单向链表分为有无头节点
头节点:一般放在第一个节点之前,其数据无意义,可以用来存放链表长度;
头指针:无头,则为第一个节点的指针,有头,则为头指针指向的节点的指针
无论什么时候头指针均不为空;
- 链表的基本操作 增删查改
链表的创建和初始化
typedef struct node {
int data;//数据域,这里以整型数据为例,也可以是其他类型
struct node* next;//指针域,用来存放下一个节点的地址,指向下一个节点
}Node;
Node* SL = NULL;//定义一个单链表,未真正初始化,需要进行初始化分配内存空间才能使
初始化
bool ListInit(Node*& SL)
{
//分配空间,如果申请分配内存失败,返回false
if ((SL = (Node*)malloc(sizeof(Node))) == NULL)
return false;
//内存申请成功
SL->data = NULL;//头节点的数据无意义
SL->next = NULL;//初始化的节点的指针指向NULL
return true;
}
判空
bool ListsEmpty(Node* SL){
//为空,返回true
if (SL->next == NULL)
return true;
//不为空,返回false
return false;
}
插入
头插
bool ListHeadAdd(Node*& SL, int data){
//如果链表未初始化,返回false
if (SL == NULL)
return false;
//插入新节点需要申请新的节点空间
Node* newnode = (Node*)malloc(sizeof(Node));
if (newnode != NULL)//新节点内存申请成功
{
newnode->data = data;//输入节点的值
newnode->next = SL->next;//使得新节点的指针指向
SL->next = newnode;
return true;
}
//内存未申请成功,返回false
return false;
}
尾插
bool ListTailAdd(Node*& SL,int data)
{
//如果链表未初始化,返回false
if (NULL == SL)
return false;
Node* newnode = (Node*)malloc(sizeof(Node));
newnode->data = data;
//遍历整个链表,找到最后一个节点
Node* p = SL;
while (p->next != NULL)//该循环结束后,遍历完链表,p指向最后一个节点,p->next为NULL
{
p = p->next;
}
//遍历到最后一个节点,插入新节点
newnode->next = p->next;
p->next = noewnode;
return true;
}
删除节点
头删法
bool ListHeadDele(Node*& SL)
{
//未初始化或链表为空,返回false
if ((SL == NULL) || (SL->next == NULL))
return false;
//删除节点需要释放空间,所以需要一个临时指针变量指向要被释放的空间
Node* tmp = SL->next;
//从链表中剔除tmp节点
SL->next = tmp->next;
//释放被删除的节点,即真正地删除被剔除的节点
free(tmp);
tmp = NULL;//防止tmp成为野指针
return true;
}
尾删法
bool ListTailDele(Node*& SL)
{
//未初始化或链表为空,返回false
if ((SL == NULL) || (SL->next == NULL))
return false;
Node* p = SL;
while (p->next->next != NULL)//该循环结束后,p指向倒数第二个节点,尾结点为p->next
{
p = p->next;
}
//释放尾节点的空间
free(p->next);
//剔除尾节点,让倒数第二个节点的指针域指向空,变成新的尾结点,
p->next = NULL;
return true;
}
遍历
void ListTraverse(Node* SL)
{
if ((SL == NULL) || (SL->next == NULL))
{
printf("链表未初始化或链表为空!\n");
return;
}
//链表不为空
Node* tmp = SL;
printf("链表元素: ");
while (tmp->next != NULL)//循环结束,tmp指向最后一个元素
{
printf("%d ", tmp->data);
tmp = tmp->next;
}
//打印最后一个元素
printf("%d\n", tmp->data);
}
链表摧毁
void ListDestroy(Node*& SL)
{
if (SL == NULL)//如果链表没有初始化,不用销毁
return;
Node* p = SL, * q = p->next;//q的作用是,在释放当前节点时,记录当前节点的下一个节点
while (q != NULL)//从头结点开始释放节点空间,一直遍历到尾结点,循环结束,p指向尾结点
{
free(p);
p = q;
q = p->next;
}
//释放尾结点,此时 q = NULL,不需要释放
free(p);
p = NULL;//防止成为野指针
}
整体代码实现:
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct node {
int data;//数据域,这里以整型数据为例,也可以是其他类型
struct node* next;//指针域,用来存放下一个节点的地址,指向下一个节点
}Node;
Node* SL = NULL;//定义一个单链表,未真正初始化,需要进行初始化分配内存空间才能使用
bool ListInit(Node*& SL)
{
//分配空间,如果申请分配内存失败,返回false
if ((SL = (Node*)malloc(sizeof(Node))) == NULL)
return false;
//内存申请成功
SL->data = NULL;
SL->next = NULL;
return true;
}
bool ListsEmpty(Node* SL){
//为空,返回true
if (SL->next == NULL)
return true;
//不为空,返回false
return false;
}
//头插法
bool ListHeadAdd(Node*& SL, int data){
//如果链表未初始化,返回false
if (SL == NULL)
return false;
//插入新节点需要申请新的节点空间
Node* newnode = (Node*)malloc(sizeof(Node));
if (newnode != NULL)//新节点内存申请成功
{
newnode->data = data;//输入节点的值
newnode->next = SL->next;//使得新节点的指针指向
SL->next = newnode;
return true;
}
//内存未申请成功,返回false
return false;
}
void ListTraverse(Node* SL)
{
if ((SL == NULL) || (SL->next == NULL))
{
printf("链表未初始化或链表为空!\n");
return;
}
//链表不为空
Node* tmp = SL;
printf("链表元素: ");
while (tmp->next != NULL)//循环结束,tmp指向最后一个元素
{
printf("%d ", tmp->data);
tmp = tmp->next;
}
//打印最后一个元素
printf("%d\n", tmp->data);
}
//从头部删除
bool ListHeadDele(Node*& SL)
{
//未初始化或链表为空,返回false
if ((SL == NULL) || (SL->next == NULL))
return false;
//删除节点需要释放空间,所以需要一个临时指针变量指向要被释放的空间
Node* tmp = SL->next;
//从链表中剔除tmp节点
SL->next = tmp->next;
//释放被删除的节点,即真正地删除被剔除的节点
free(tmp);
tmp = NULL;//防止tmp成为野指针
return true;
}
void ListDestroy(Node*& SL)
{
if (SL == NULL)//如果链表没有初始化,不用销毁
return;
Node* p = SL, * q = p->next;//q的作用是,在释放当前节点时,记录当前节点的下一个节点
while (q != NULL)//从头结点开始释放节点空间,一直遍历到尾结点,循环结束,p指向尾结点
{
free(p);
p = q;
q = p->next;
}
//释放尾结点,此时 q = NULL,不需要释放
free(p);
p = NULL;//防止成为野指针
}
int main() {
if (ListInit(SL)) cout << "YES" << endl;
else cout << "NO" << endl;
ListHeadAdd(SL, 5);
ListHeadAdd(SL, 6);
ListHeadAdd(SL, 7);
ListHeadAdd(SL, 8);
ListTraverse(SL);
ListHeadDele(SL);
ListTraverse(SL);
ListDestroy(SL);
ListTraverse(SL);
return 0;
}
运行结果