线性表的顺序存储结构和链式存储结构及二者的简单操作(C,C++混用)

线性表的顺序存储结构和链式存储结构及二者的简单操作(C,C++混用)

一、前言:

​ 在学数据结构的时候,第一次上机实验,老师让我们实现线性表的顺序存储结构和链式存储结构及其简单操作,看着就脑阔疼。书上的代码吧,都是伪代码,照着敲出来n多报错(我们用的是清华大学出版社严蔚敏、陈文博编著的《数据结构及应用算法程序(修订版)》,书挺好的,就是有些地方不太照顾初学者。反正就是看着脑瓜子嗡嗡的,但搞懂了之后满满的都是成就感,让人又爱又恨,感兴趣的小伙伴可以看看);上网搜前人的成果吧,无一例外都报错七八十个(有可能是我自己的原因,没别的意思)。

​ 一怒之下,我熬了两个通宵终究还是实现了(在实现过程中我也深刻体会到一个好的编译器对码农的帮助有多大,写顺序表的时候我用的VC++6.0,找错是找的我头都秃了,写链表的时候我换了VS2010,报错处有红色波浪线,改错那是嘎嘎快)。一直有想写个博客记录一下我的努力成果,但总是由于各种原因不了了之,今天我终于还是写了这篇博客。

​ 顺序表和链表概念之类的我就不做介绍了,网上一搜,写得好的博主大有人在,咱就不赘述了;下面是顺序表及其简单操作,和链表及其简单操作,用c和c++混用实现,具体有哪些操作在头文件注释里找吧(里面的注释可能有我个人的一些标注,我懒得删了,将就着看吧)

二、线性表的顺序存储结构及其简单操作(多模块):

首先肯定要创建一个WIN32控制台应用程序的空项目的(在分多模块时一定要注意每个源程序文件引入头文件)

1.创建头文件Definition.h:

#include <stdio.h>
#include <process.h> //至少ErrorMessage中要用到
#include <iostream.h>//至少ErrorMessage中要用到
const int LIST_INIT_SIZE=100;//线性表(默认的)初始分配最大空间量
const int LISTINCREMENT=10;//默认的增补空间量
//定义线性表SqList类型
typedef int ElemType;
typedef struct
{
	ElemType *elem;
	int length;
	int listsize;
	int incrementsize;
}SqList;
//顺序表的初始化
//C语言没有默认参数用法,所以可能要C和C++混用
void InitList_Sq(SqList &L,int maxsize=LIST_INIT_SIZE,int incresize=LISTINCREMENT);
//将初始化后的顺序表前十个元素分别赋值为1-10
void NatureList1_10_Sq(SqList &L);
//顺序表查找元素
//在L查找第一个与e相等的元素,若能找到返回其在L的位序,否则返回0
int LocateElem_Sq(SqList L,ElemType e);
/*接下来的三个函数都是为了实现顺序表的插入*/
//出错信息处理函数
void ErrorMessage(char *s);
//顺序表追加空间
void increment(SqList &L);
//顺序表插入元素
//在顺序表L的第i个元素前插入新的元素e ,1<=i<=L.length+1,容量不足按预定义增量扩容
void ListInsert_Sq(SqList &L,int i,ElemType e);
//顺序表删除元素
//在顺序表L中删除第i个元素,并用e返回其值,1<=i<=L.length
void ListDelete_Sq(SqList &L,int i,ElemType &e);//用到了ErrorMessage
//顺序表的销毁
//释放顺序表L所占的储存空间
void DestroyList_Sq(SqList &L);
//顺序表的显示
//因为查找元素时顺序是反的,为了探明原因,写一个显示顺序表的函数
void PrintList_Sq(SqList L);


2.创建源程序文件InitList_Sq.cpp:

//顺序表的初始化
//C语言没有默认常数用法,所以可能要C和C++混用
#include "Definition.h"
void InitList_Sq(SqList &L,int maxsize,int incresize)
{
	L.elem=new ElemType[maxsize];//为顺序表分配一个最大容量为maxsize的数组空间
	L.length=0;
	L.listsize=maxsize;
	L.incrementsize=incresize;
}


3.创建源程序文件NatureList1_10_Sq.cpp:

//将初始化后的顺序表前十个元素分别赋值为1-10
#include "Definition.h"
void NatureList1_10_Sq(SqList &L)
{
	for(int i=0;i<=9;i++)
	{
		L.elem[i]=i+1;
	}
	L.length=10;
}


4.创建源程序文件LocateElem_Sq.cpp:

//顺序表查找元素
//在L查找第一个与e相等的元素,若能找到返回其在L的位序,否则返回0
#include "Definition.h"
int LocateElem_Sq(SqList L,ElemType e)
{
	int i=1;
	ElemType *p=L.elem;
	while(i<=L.length && *(p++)!=e) i++;
	if(i<=L.length) return i;
	else return 0;
}//LocateElem_Sq

5.创建源程序文件ErrorMessage.cpp:

//出错信息处理函数
#include "Definition.h"
void ErrorMessage(char *s)
{
	cout<<s<<endl;
	exit(1);
}

6.创建源程序文件increment.cpp:

//顺序表追加空间
#include "Definition.h"
void increment(SqList &L)
{
	ElemType *a;//??标记一下这里可能会出问题??
	a=new ElemType [L.listsize+L.incrementsize];
	for(int i=0;i<=L.length;i++)
		a[i]=L.elem[i];
	delete[] L.elem;
	L.elem=a;
	L.listsize=L.listsize+L.incrementsize;
}

7.创建源程序文件ListInsert_Sq.cpp:

//顺序表插入元素
//在顺序表L的第i个元素前插入新的元素e ,1<=i<=L.length+1,容量不足按预定义增量扩容
#include "Definition.h"
void ListInsert_Sq(SqList &L,int i,ElemType e)
{
	if(i<1||i>L.length+1)
		ErrorMessage("i值不合法");
	if(L.length>=L.listsize)
		increment(L);//'>'应该可以不要
	ElemType *q=&(L.elem[i-1]);
	for(ElemType *p=&(L.elem[L.length-1]);p>=q;p--)
		*(p+1)=*p;
	*q=e;
	L.length++;
}//ListInsert_Sq

8.创建源程序文件ListDelete_Sq.cpp:

//顺序表删除元素
//在顺序表L中删除第i个元素,并用e返回其值,1<=i<=L.length
#include "Definition.h"
void ListDelete_Sq(SqList &L,int i,ElemType &e)
{
	if((i<1)||(i>L.length)) 
		ErrorMessage("i值不合法");
	ElemType *p=&(L.elem[i-1]);
	e=*p;
	ElemType *q=L.elem+L.length-1;
	for(++p;p<=q;p++)
		*(p-1)=*p;
	L.length--;
}

9.创建源程序文件DestroyList_Sq.cpp:

//顺序表的销毁
//释放顺序表L所占的储存空间
#include "Definition.h"
void DestroyList_Sq(SqList &L)
{
	delete[] L.elem;
	L.listsize=0;
	L.length=0;
}//DestroyList_Sq

10.创建源程序文件PrintList_Sq.cpp:

//顺序表的显示
//因为查时顺序是反的,为了探明原因,写一个显示顺序表的函数
#include "Definition.h"
void PrintList_Sq(SqList L)
{
	printf("当前顺序表所有元素:");
	for (int i=0;i<L.length; i++)
	{
		printf("%d ", L.elem[i]);
	}
	printf("\n");
}//PrintList_Sq

11.创建(主函数)源程序文件Main_Sq.cpp:

#include "Definition.h"
int main()
{
    SqList A;
	printf("\n\n");
    int flag;
    printf("******************************************************\n");
    printf("*************choose the operation of List*************\n");
    printf("*****************1-顺序表的初始化*********************\n");
	printf("*****************2-得到1-10的自然顺序表***************\n");
	printf("*****************3-顺序表的显示***********************\n");
    printf("*****************4-顺序表查找元素*********************\n");
    printf("*****************5-顺序表插入元素*********************\n");
    printf("*****************6-顺序表删除元素*********************\n");
    printf("*****************7-顺序表的销毁***********************\n");
    printf("*****************0-退出*******************************\n");
    printf("******************************************************\n");
    printf("\n\n");
	

    while(1){
    	printf("Input the function you want to chose:\n");
    	scanf("%d",&flag);
    	if(flag==0||flag==1||flag==2||flag==3||flag==4||flag==5||flag==6||flag==7)
    	{
    		printf("The function is=%d\n",flag);
    		switch(flag)
    		{
    		case 1:
    			
    			{
    				InitList_Sq(A);
    				printf("顺序表初始化成功\n");
    				break;
    			}
    		case 2:
    			{
    				NatureList1_10_Sq(A);
    				printf("已得到1-10的自然顺序表\n");
    				break;
    			}
    		case 3:
    			{
    				printf("当前顺序表为:\n");
    				PrintList_Sq(A);
    				break;
    			}
    		case 4:
    			{
    				int a,pos;
    				printf("请输入你要查找的元素值\n");
    				scanf("%d",&a);
    				pos=LocateElem_Sq(A,a);
    				printf("你要查找的元素值最早出现在第%d位\n",pos);
    				printf("注:若显示0则顺序表中无该元素\n");
    				break;
    			}
    		case 5:
    			{
    				int pos;
    				ElemType a;
    				printf("请输入你要(前)插入元素的位置和值:\n");
    				scanf("%d%d",&pos,&a);
    				ListInsert_Sq(A,pos,a);
    				printf("插入元素成功\n");
    				break;
    			}
    		case 6:
    			{
    				int pos;
    				ElemType a;
    				printf("请输入你要删除元素的位置:\n");
    				scanf("%d",&pos);
    				ListDelete_Sq(A,pos,a);
    				printf("你删除的元素为%d\n",a);
    				break;
    			}
    		case 7:
    			{
    				DestroyList_Sq(A);
    				printf("销毁成功\n");
    				break;
    			}
    		case 0:
    			printf("you choose to exit\nGoodbye!\n");
    			return 0;
    		}
    	}
    	else ErrorMessage("请在菜单内挑选功能");
    }
    return 0;

}


三、顺序表的顺序存储结构及其简单操作(两模块):

1.创建头文件Definition.h:

#include <stdio.h>
#include <process.h> //至少ErrorMessage中要用到
#include <iostream>//至少ErrorMessage中要用到
using namespace std;
const int LIST_INIT_SIZE=100;//线性表(默认的)初始分配最大空间量
const int LISTINCREMENT=10;//默认的增补空间量
//定义线性表SqList类型
typedef int ElemType;
typedef struct
{
	ElemType *elem;
	int length;
	int listsize;
	int incrementsize;
}SqList;
//顺序表的初始化
//C语言没有默认常数用法,所以可能要C和C++混用
void InitList_Sq(SqList &L,int maxsize=LIST_INIT_SIZE,int incresize=LISTINCREMENT);
//将初始化后的顺序表前十个元素分别赋值为1-10
void NatureList1_10_Sq(SqList &L);
//顺序表查找元素
//在L查找第一个与e相等的元素,若能找到返回其在L的位序,否则返回0
int LocateElem_Sq(SqList L,ElemType e);
/*接下来的三个函数都是为了实现顺序表的插入*/
//出错信息处理函数
void ErrorMessage(char *s);
//顺序表追加空间
void increment(SqList &L);
//顺序表插入元素
//在顺序表L的第i个元素前插入新的元素e ,1<=i<=L.length+1,容量不足按预定义增量扩容
void ListInsert_Sq(SqList &L,int i,ElemType e);
//顺序表删除元素
//在顺序表L中删除第i个元素,并用e返回其值,1<=i<=L.length
void ListDelete_Sq(SqList &L,int i,ElemType &e);//用到了ErrorMessage
//顺序表的销毁
//释放顺序表L所占的储存空间
void DestroyList_Sq(SqList &L);
//顺序表的显示
//因为查找元素时顺序是反的,为了探明原因,写一个显示顺序表的函数
void PrintList_Sq(SqList L);
//顺序表的初始化
//C语言没有默认常数用法,所以可能要C和C++混用
void InitList_Sq(SqList &L,int maxsize,int incresize)
{
	L.elem=new ElemType[maxsize];//为顺序表分配一个最大容量为maxsize的数组空间
	L.length=0;
	L.listsize=maxsize;
	L.incrementsize=incresize;
}
//将初始化后的顺序表前十个元素分别赋值为1-10
void NatureList1_10_Sq(SqList &L)
{
	for(int i=0;i<=9;i++)
	{
		L.elem[i]=i+1;
	}
	L.length=10;
}
//顺序表的显示
//因为查找元素时顺序是反的,为了探明原因,写一个显示顺序表的函数
void PrintList_Sq(SqList L)
{
	printf("当前顺序表所有元素:");
	for (int i=0;i<L.length; i++)
	{
		printf("%d ", L.elem[i]);
	}
	printf("\n");
}//PrintList_Sq
//顺序表查找元素
//在L查找第一个与e相等的元素,若能找到返回其在L的位序,否则返回0
int LocateElem_Sq(SqList L,ElemType e)
{
	int i=1;
	ElemType *p=L.elem;
	while(i<=L.length && *(p++)!=e) i++;
	if(i<=L.length) return i;
	else return 0;
}//LocateElem_Sq
/*接下来的三个函数都是为了实现顺序表的插入*/
//出错信息处理函数
void ErrorMessage(char *s)
{
	cout<<s<<endl;
	exit(1);
}
//顺序表追加空间
void increment(SqList &L)
{
	ElemType *a;//??标记一下这里可能会出问题??
	a=new ElemType [L.listsize+L.incrementsize];
	for(int i=0;i<=L.length;i++)
		a[i]=L.elem[i];
	delete[] L.elem;
	L.elem=a;
	L.listsize=L.listsize+L.incrementsize;
}
//顺序表插入元素
//在顺序表L的第i个元素前插入新的元素e ,1<=i<=L.length+1,容量不足按预定义增量扩容
void ListInsert_Sq(SqList &L,int i,ElemType e)
{
	if(i<1||i>L.length+1)
		ErrorMessage("i值不合法");
	if(L.length>=L.listsize)
		increment(L);//'>'应该可以不要
	ElemType *q=&(L.elem[i-1]);
	for(ElemType *p=&(L.elem[L.length-1]);p>=q;p--)
		*(p+1)=*p;
	*q=e;
	L.length++;
}//ListInsert_Sq
//顺序表删除元素
//在顺序表L中删除第i个元素,并用e返回其值,1<=i<=L.length
void ListDelete_Sq(SqList &L,int i,ElemType &e)
{
	if((i<1)||(i>L.length)) 
		ErrorMessage("i值不合法");
	ElemType *p=&(L.elem[i-1]);
	e=*p;
	ElemType *q=L.elem+L.length-1;
	for(++p;p<=q;p++)
		*(p-1)=*p;
	L.length--;
}
//顺序表的销毁
//释放顺序表L所占的储存空间
void DestroyList_Sq(SqList &L)
{
	delete[] L.elem;
	L.listsize=0;
	L.length=0;
}//DestroyList_Sq

2.创建(主函数)源程序文件Main_Lk.cpp:

#include "Definition.h"
int main()
{
    SqList A;
	printf("\n\n");
    int flag;
    printf("******************************************************\n");
    printf("*************choose the operation of List*************\n");
    printf("*****************1-顺序表的初始化*********************\n");
	printf("*****************2-得到1-10的自然顺序表***************\n");
	printf("*****************3-顺序表的显示***********************\n");
    printf("*****************4-顺序表查找元素*********************\n");
    printf("*****************5-顺序表插入元素*********************\n");
    printf("*****************6-顺序表删除元素*********************\n");
    printf("*****************7-顺序表的销毁***********************\n");
    printf("*****************0-退出*******************************\n");
    printf("******************************************************\n");
    printf("\n\n");
	
    while(1){
		printf("Input the function you want to chose:\n");
		scanf("%d",&flag);
		if(flag==0||flag==1||flag==2||flag==3||flag==4||flag==5||flag==6||flag==7)
		{
			printf("The function is=%d\n",flag);
			switch(flag)
			{
			case 1:
				
				{
					InitList_Sq(A);
					printf("顺序表初始化成功\n");
					break;
				}
			case 2:
				{
					NatureList1_10_Sq(A);
					printf("已得到1-10的自然顺序表\n");
					break;
				}
			case 3:
				{
					printf("当前顺序表为:\n");
					PrintList_Sq(A);
					break;
				}
			case 4:
				{
					int a,pos;
					printf("请输入你要查找的元素值\n");
					scanf("%d",&a);
					pos=LocateElem_Sq(A,a);
					printf("你要查找的元素值最早出现在第%d位\n",pos);
					printf("注:若显示0则顺序表中无该元素\n");
					break;
				}
			case 5:
				{
					int pos;
					ElemType a;
					printf("请输入你要(前)插入元素的位置和值:\n");
					scanf("%d%d",&pos,&a);
					ListInsert_Sq(A,pos,a);
					printf("插入元素成功\n");
					break;
				}
			case 6:
				{
					int pos;
					ElemType a;
					printf("请输入你要删除元素的位置:\n");
					scanf("%d",&pos);
					ListDelete_Sq(A,pos,a);
					printf("你删除的元素为%d\n",a);
					break;
				}
			case 7:
				{
					DestroyList_Sq(A);
					printf("销毁成功\n");
					break;
				}
			case 0:
				printf("you choose to exit\nGoodbye!\n");
				return 0;
			}
		}
		else ErrorMessage("请在菜单内挑选功能");
	}
    return 0;
}

四、链表的顺序存储结构及其简单操作(多模块):

1.创建头文件Difinition.h:

#include <stdio.h>
#include <process.h> //至少ErrorMessage中要用到
#include <iostream>//至少ErrorMessage中要用到
using namespace std;

const int LIST_INIT_SIZE=5;//链表默认长度为5

typedef int ElemType;//声明ElemType
//(单)链表的储存表示
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LinkList;//??可能有问题,标记一下??
//初始化一个长度为n的链表,默认长度为LIST_INIT_SIZE
void ListCreat_Lk(LinkList *&head,int n=LIST_INIT_SIZE);//特别要注意*&head
//遍历链表(逐项输出)
void TravelList_Lk(LinkList *head);
//求链表的长度
int ListLength_Lk(LinkList *head);
//查找链表中的元素,显示其节点位序
void LocateElem_Lk(LinkList *head,ElemType e);
//出错信息处理函数
void ErrorMessage(char *s);
//链表节点插入(前插)
//在第i个元素前插入一个元素e
void InsertElem_Lk(LinkList *&head,int i,ElemType e);//特别要注意*&head
//删除链表的第i个元素,并用e返回其值
void DeleteElem_Lk(LinkList *&head,int i,ElemType &e);//特别要注意*&head
//链表的销毁
//从第一个元素开始逐个删除
void DestroyList_Lk(LinkList *&head);//特别要注意*&head

2.创建源程序文件ListCreat_Lk.cpp:

//初始化一个长度为n的链表,默认长度为LIST_INIT_SIZE
#include "Difinition.h"//Definition打错了,将就着用吧
void ListCreat_Lk(LinkList *&head,int n)
{
	LinkList *node,*end;//定义头节点,普通节点,尾部节点;
	head=new LinkList;//分配地址
	end=head;//若是空链表则头尾节点一样
	for(int i=0;i<n;i++)
	{
		node=new LinkList;
		scanf("%d",&node->data);
		end->next=node;
		end=node;
	}
	end->next=NULL;//结束创建
}//LinkCreat_Lk

3.创建源程序文件TravelList_Lk.cpp:

//遍历链表(逐项输出)
#include "Difinition.h"//Definition打错了,将就着用吧
void TravelList_Lk(LinkList *head)
{
    LinkList *p=head->next;
    while(p!=NULL)
	{
        printf("%d\t",p->data);
        p=p->next;
    }
    printf("\n");
}//TravelList_Lk

4.创建源程序文件ListLength_Lk.cpp:

//求链表的长度
#include "Difinition.h"//Definition打错了,将就着用吧
int ListLength_Lk(LinkList *head)
{
	LinkList *p=head->next;
	int k=0;
	while(p)
	{
		p=p->next;
		k++;
	}
	return k;
}//ListLength_Lk

5.创建源程序文件LocateElem_Lk.cpp:

//查找链表中的元素,显示其节点位序
#include "Difinition.h"//Definition打错了,将就着用吧
void LocateElem_Lk(LinkList *head,ElemType e)
{
	int k=0;
	LinkList *p=head;
	while(p&&p->data!=e)
	{
		p=p->next;
		k++;
	}
	if(p==NULL) k=0;
	printf("你所查找的元素最先出现的位序为:%d\n",k);
	printf("注:若显示0则该链表无所查元素\n");
}//LocateList_Lk

6.创建源程序文件ErrorMessage.cpp:

//出错信息处理函数
#include "Difinition.h"//Definition打错了,将就着用吧
void ErrorMessage(char *s)
{
	cout<<s<<endl;
	exit(1);
}//ErrorMessage

7.创建源程序文件InsertElem_Lk.cpp:

//链表节点插入(前插)
//在第i个元素前插入一个元素e
#include "Difinition.h"//Definition打错了,将就着用吧
void InsertElem_Lk(LinkList *&head,int i,ElemType e)//特别要注意*&head
{
	int k=ListLength_Lk(head);
	if(i<1||i>k) ErrorMessage("i值不合法");
	else if(i==1)
	{
		LinkList *p=new LinkList;
		p->data=e;
		p->next=head->next;
		head->next=p;
	}
	else
	{
		LinkList *q=head;
		for(i=i-1;i>0;i--)
		{
			q=q->next;
		}
		LinkList *p=new LinkList;
		p->data=e;
		p->next=q->next;
		q->next=p;
	}
}//InsertElem_Lk

8.创建源程序文件DeleteElem_Lk.cpp:

//删除链表的第i个元素,并用e返回其值
#include "Difinition.h"//Definition打错了,将就着用吧
void DeleteElem_Lk(LinkList *&head,int i,ElemType &e)//特别要注意*&head
{
	int k=ListLength_Lk(head);
	if(i<1||i>k) ErrorMessage("i值不合法");
	else if(i==1)
	{
		LinkList *p=head->next;
		head->next=p->next;
		e=p->data;
		delete p;
	}
	else
	{
		LinkList *q=head;
		for(i=i-1;i>0;i--)
		{
			q=q->next;
		}
		LinkList *p=q->next;
		e=p->data;
		q->next=p->next;
		delete p;
	}
}//DeleteElem_Lk

9.创建源程序文件DestroyList_Lk.cpp:

//链表的销毁
//从第一个元素开始逐个删除
#include "Difinition.h"//Definition打错了,将就着用吧
void DestroyList_Lk(LinkList *&head)//特别要注意*&head
{
    LinkList *p;
    while(head->next!=NULL)
	{
        p=head->next;
        head->next=p->next;
		delete p;
    }
}//DestroyLink_Lk

10.创建源程序文件Main_Lk.cpp:

#include "Difinition.h"//Definition打错了,将就着用吧
int main()
{
    LinkList *head1;//LinkList *head1=new LinkList;也可去除警告
	head1=NULL;
	printf("\n\n");
    int flag;
    printf("**************************************************************\n");
    printf("*****************choose the operation of List*****************\n");
    printf("*********************1-链表的初始化***************************\n");
	printf("*********************2-链表的遍历(逐项输出)*****************\n");
	printf("*********************3-求链表的长度***************************\n");
    printf("*********************4-查找链表的元素*************************\n");
    printf("*********************5-链表的元素插入*************************\n");
    printf("*********************6-链表的元素删除*************************\n");
    printf("*********************7-链表的销毁*****************************\n");
    printf("*********************0-退出***********************************\n");
    printf("**************************************************************\n");
	printf("****注:此程序涉及的链表带头结点,但不参与长度和位序的计算****\n");
    printf("\n\n");
	
    while(1){
		printf("Input the function you want to chose:\n");
		scanf("%d",&flag);
		if(flag==0||flag==1||flag==2||flag==3||flag==4||flag==5||flag==6||flag==7)
		{
			printf("The function is=%d\n",flag);
			switch(flag)
			{
			case 1:
				{
					printf("请逐个输入链表的五个值:\n");
					ListCreat_Lk(head1);
					printf("链表初始化成功(长度为5)\n");
					break;
				}
			case 2:
				{
					printf("当前链表为:\n");
					TravelList_Lk(head1);
					break;
				}
			case 3:
				{
					int len=ListLength_Lk(head1);
					printf("当前链表长度为:%d\n",len);
					break;
				}
			case 4:
				{
					int a;
					printf("请输入你要查找的元素值\n");
					scanf("%d",&a);
					LocateElem_Lk(head1,a);
					break;
				}
			case 5:
				{
					int pos;
					ElemType a;
					printf("请输入你要(前)插入元素的位置和值:\n");
					scanf("%d%d",&pos,&a);
					InsertElem_Lk(head1,pos,a);
					printf("插入元素成功\n");
					break;
				}
			case 6:
				{
					int pos;
					ElemType a;
					printf("请输入你要删除元素的位置:\n");
					scanf("%d",&pos);
					DeleteElem_Lk(head1,pos,a);
					printf("你删除的元素为%d\n",a);
					break;
				}
			case 7:
				{
					DestroyList_Lk(head1);
					printf("销毁成功\n");
					break;
				}
			case 0:
				printf("you choose to exit\nGoodbye!\n");
				return 0;
			}
		}
		else ErrorMessage("请在菜单内挑选功能");
	}
    return 0;
}
/*"."一般情况下理解为"的”
“->”一般理解为"指向的结构体的"
即引用结构体变量中的元素,若变量是一般的结构体变量用“.”,若为指针则用“->”
注意区别头结点和头指针*/

五、链表的顺序存储结构及其简单操作(两模块):

1.创建头文件Definition.h:

#include <stdio.h>
#include <process.h> //至少ErrorMessage中要用到
#include <iostream>//至少ErrorMessage中要用到
using namespace std;

const int LIST_INIT_SIZE=5;//链表默认长度为5

typedef int ElemType;//声明ElemType
//(单)链表的储存表示
typedef struct LNode
{
	ElemType data;
	struct LNode *next;
}LinkList;//??可能有问题,标记一下??
//初始化一个长度为n的链表,默认长度为LIST_INIT_SIZE
void ListCreat_Lk(LinkList *&head,int n=LIST_INIT_SIZE);//特别要注意*&head
//遍历链表(逐项输出)
void TravelList_Lk(LinkList *head);
//求链表的长度
int ListLength_Lk(LinkList *head);
//查找链表中的元素,显示其节点位序
void LocateElem_Lk(LinkList *head,ElemType e);
//出错信息处理函数
void ErrorMessage(char *s);
//链表节点插入(前插)
//在第i个元素前插入一个元素e
void InsertElem_Lk(LinkList *&head,int i,ElemType e);//特别要注意*&head
//删除链表的第i个元素,并用e返回其值
void DeleteElem_Lk(LinkList *&head,int i,ElemType &e);//特别要注意*&head
//链表的销毁
//从第一个元素开始逐个删除
void DestroyList_Lk(LinkList *&head);//特别要注意*&head
//初始化一个长度为n的链表,默认长度为LIST_INIT_SIZE
void ListCreat_Lk(LinkList *&head,int n)
{
	LinkList *node,*end;//定义头节点,普通节点,尾部节点;
	head=new LinkList;//分配地址
	end=head;//若是空链表则头尾节点一样
	for(int i=0;i<n;i++)
	{
		node=new LinkList;
		scanf("%d",&node->data);
		end->next=node;
		end=node;
	}
	end->next=NULL;//结束创建
}//LinkCreat_Lk
//遍历链表(逐项输出)
void TravelList_Lk(LinkList *head)
{
    LinkList *p=head->next;
    while(p!=NULL)
	{
        printf("%d\t",p->data);
        p=p->next;
    }
    printf("\n");
}//TravelList_Lk
//求链表的长度
int ListLength_Lk(LinkList *head)
{
	LinkList *p=head->next;
	int k=0;
	while(p)
	{
		p=p->next;
		k++;
	}
	return k;
}//ListLength_Lk
//查找链表中的元素,显示其节点位序
void LocateElem_Lk(LinkList *head,ElemType e)
{
	int k=0;
	LinkList *p=head;
	while(p&&p->data!=e)
	{
		p=p->next;
		k++;
	}
	if(p==NULL) k=0;
	printf("你所查找的元素最先出现的位序为:%d\n",k);
	printf("注:若显示0则该链表无所查元素\n");
}//LocateList_Lk
//出错信息处理函数
void ErrorMessage(char *s)
{
	cout<<s<<endl;
	exit(1);
}//ErrorMessage
//链表节点插入(前插)
//在第i个元素前插入一个元素e
void InsertElem_Lk(LinkList *&head,int i,ElemType e)//特别要注意*&head
{
	int k=ListLength_Lk(head);
	if(i<1||i>k) ErrorMessage("i值不合法");
	else if(i==1)
	{
		LinkList *p=new LinkList;
		p->data=e;
		p->next=head->next;
		head->next=p;
	}
	else
	{
		LinkList *q=head;
		for(i=i-1;i>0;i--)
		{
			q=q->next;
		}
		LinkList *p=new LinkList;
		p->data=e;
		p->next=q->next;
		q->next=p;
	}
}//InsertElem_Lk
//删除链表的第i个元素,并用e返回其值
void DeleteElem_Lk(LinkList *&head,int i,ElemType &e)//特别要注意*&head
{
	int k=ListLength_Lk(head);
	if(i<1||i>k) ErrorMessage("i值不合法");
	else if(i==1)
	{
		LinkList *p=head->next;
		head->next=p->next;
		e=p->data;
		delete p;
	}
	else
	{
		LinkList *q=head;
		for(i=i-1;i>0;i--)
		{
			q=q->next;
		}
		LinkList *p=q->next;
		e=p->data;
		q->next=p->next;
		delete p;
	}
}//DeleteElem_Lk
//链表的销毁
//从第一个元素开始逐个删除
void DestroyList_Lk(LinkList *&head)//特别要注意*&head
{
    LinkList *p;
    while(head->next!=NULL)
	{
        p=head->next;
        head->next=p->next;
		delete p;
    }
}//DestroyLink_Lk


2.创建(主函数)源程序文件Main_Lk.cpp:

#include "Difinition.h"//Definition打错了,将就着用吧
int main()
{
    LinkList *head1;//LinkList *head1=new LinkList;也可去除警告
	head1=NULL;
	printf("\n\n");
    int flag;
    printf("**************************************************************\n");
    printf("*****************choose the operation of List*****************\n");
    printf("*********************1-链表的初始化***************************\n");
	printf("*********************2-链表的遍历(逐项输出)*****************\n");
	printf("*********************3-求链表的长度***************************\n");
    printf("*********************4-查找链表的元素*************************\n");
    printf("*********************5-链表的元素插入*************************\n");
    printf("*********************6-链表的元素删除*************************\n");
    printf("*********************7-链表的销毁*****************************\n");
    printf("*********************0-退出***********************************\n");
    printf("**************************************************************\n");
	printf("****注:此程序涉及的链表带头结点,但不参与长度和位序的计算****\n");
    printf("\n\n");
	

    while(1){
    	printf("Input the function you want to chose:\n");
    	scanf("%d",&flag);
    	if(flag==0||flag==1||flag==2||flag==3||flag==4||flag==5||flag==6||flag==7)
    	{
    		printf("The function is=%d\n",flag);
    		switch(flag)
    		{
    		case 1:
    			{
    				printf("请逐个输入链表的五个值:\n");
    				ListCreat_Lk(head1);
    				printf("链表初始化成功(长度为5)\n");
    				break;
    			}
    		case 2:
    			{
    				printf("当前链表为:\n");
    				TravelList_Lk(head1);
    				break;
    			}
    		case 3:
    			{
    				int len=ListLength_Lk(head1);
    				printf("当前链表长度为:%d\n",len);
    				break;
    			}
    		case 4:
    			{
    				int a;
    				printf("请输入你要查找的元素值\n");
    				scanf("%d",&a);
    				LocateElem_Lk(head1,a);
    				break;
    			}
    		case 5:
    			{
    				int pos;
    				ElemType a;
    				printf("请输入你要(前)插入元素的位置和值:\n");
    				scanf("%d%d",&pos,&a);
    				InsertElem_Lk(head1,pos,a);
    				printf("插入元素成功\n");
    				break;
    			}
    		case 6:
    			{
    				int pos;
    				ElemType a;
    				printf("请输入你要删除元素的位置:\n");
    				scanf("%d",&pos);
    				DeleteElem_Lk(head1,pos,a);
    				printf("你删除的元素为%d\n",a);
    				break;
    			}
    		case 7:
    			{
    				DestroyList_Lk(head1);
    				printf("销毁成功\n");
    				break;
    			}
    		case 0:
    			printf("you choose to exit\nGoodbye!\n");
    			return 0;
    		}
    	}
    	else ErrorMessage("请在菜单内挑选功能");
    }
    return 0;

}
/*"."一般情况下理解为"的”
“->”一般理解为"指向的结构体的"
即引用结构体变量中的元素,若变量是一般的结构体变量用“.”,若为指针则用“->”
注意区别头结点和头指针*/

六、后记:

​ 到这里,我终于快写完了我的第一篇博客,我感觉我快要升华了。言归正传,如果要纯c语言实现,将cout换成printf,const改用#dfine,默认参数略作修改,new改用malloc……即可;反之若要纯c++实现(因为c++完全兼容c,我不确定这种说法对不对哈,明白什么意思就行),只需将printf换成cout……,……,……即可。因为我比较懒,就不想再搞了,就这么将就着看(用吧)。至于演示结果,截图不知道放哪了,就省略了吧。

​ 再次提醒,注释里面可能有我在编写/调试过程中的一些杂七杂八的个人标注,看不懂就当没看见就好,我自己往回看我自己可能都看不懂……嗯,就是懒得删了。

​ 第一篇博客,难免有错,欢迎斧正。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ParkyTin

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

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

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

打赏作者

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

抵扣说明:

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

余额充值