考研数据结构

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.栈

(优点:简洁且节省空间)

基本操作

  1. InitStack(&S)初始化一个空栈
  2. StackEmpty(S)判断栈S是否为空
  3. Push(&S,x)进栈
  4. Pop(&S,&x)出栈
  5. GetTop(S,&x)读取栈顶元素
  6. DestroyStack(&S)销毁栈,释放其空间

  • 顺序栈
  1. 思路:利用一组地址连续的存储单元存放底部到顶部的所有数据,同时利用一个指针指示栈顶元素。

  1. 初始化

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.链表

链表

  • 单向链表

  1. 包括两部分:数据域和指针域
Typedef struct student {

       Int num;//数据域 存放本节点的数据

       Struct student *next;//指针域 存放下一个节点的首地址

}STU;
  1. 单向链表分为有无头节点

头节点:一般放在第一个节点之前,其数据无意义,可以用来存放链表长度;

       头指针:无头,则为第一个节点的指针,有头,则为头指针指向的节点的指针      

              无论什么时候头指针均不为空;

    

                                                                                                                          

  1. 链表的基本操作 增删查改

链表的创建和初始化

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;

}



运行结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值