线性表的两种实现(附C与java代码)
2.1 认识线性表
线性表的定义:用数据元素的有限序列表示
同一线性表中的元素必定具有相同特性。
线性表中的数据元素可以为简单类型,也可以为复杂类型
线性表基本操作:
- 初始化
- 取值
- 查找
- 插入
- 删除
- 是否为空
- 线性表长度
2.2 线性表的顺序存储结构实现(数组实现)
C语言中我们定义一个数据结构是通过结构体的定义来实现
#define MAXSIZE 100 //定义最大长度
typedef int ElemType;
//表示 ElemType是int类型,typedef 是起别名的意思
typedef struct ListCollection{
ElemType Data[MAXSIZE];
// 一种自定义的数据类型,也可以是基本类型
int index;
}*List;
//*List是指向ListCollection这个结构体的一个指针,起别名
而在Java中我们通过类class来实现,后面的方法也是在Java类实现,就是写一个类,带上各种方法
public class ListCollection{
int[] Data;
int index;
}
初始化操作
//C语言的初始化操作,首先需要申请一块内存空间
List MakeList(){List list;
list = (List)malloc(sizeof(struct ListCollection)); //申请一块空间
list->index=-1; // 让长度变为-1,说明里面没有元素,即下标为index
return list;
}
// java的初始化操作,通过构造方法
ListCollection(int max){Data = new int[max];
index = -1;
}
是否为空
//C语言实现,对于C语言不用boolean,用0表示false,1是true
int isEmpty(List list){return list->index < 0 ? 1 : 0;
}
//java 实现
boolean isEmpty(){return index < 0 ? true: false;
}
获取长度
//C语言实现
int getSize(List list){return list->index;
}
//java实现 复杂度O(1)
int getSize(){return index;
}
取值
//C语言实现
ElemType getValue(int i,List list){if(i>list->index||i<0) return -1;
return list->Data[i];
}
//java 实现 复杂度O(1)
int getValue(int i){if(i>index||i<0) return -1;
return Data[i];
}
查找
//C语言实现,复杂度O(n)
int find(ElemType value,List list){int i;
if(isEmpty(list)) return -1;
for(i=0;i <= list->index;++i){
if(list->Data[i]==value) return i;
}
return -1;
}
// 简单线性查找,复杂度O(n)
int find(int value){if(isEmpty()) return -1;
for(int i = 0;i <= index; ++i){
if(Data[i]==value) return i;
}
return -1;
}
插入
// C语言实现
int insert(int i,ElemType value,List list){int j;
if(list->index==MAXSIZE-1){
printf("已满");
return 0;
}
if(i>list->index+1||i<0){
printf("插入位置不正确");
return 0;
}
for(j=list->index;j>=i;--j){
list->Data[j+1]=list->Data[j];
}
list->Data[i]=value;
list->index++;
return 1;
}
//java 实现 复杂度O(n)
boolean insert(int i,int value){if(i>index+1||i<0||index==Data.length()-1)
return false;// i的位置不合法,或者线性表已满
for(int j=index;j>=i;--j){
Data[j+1] = Data[j];
// 从后往前遍历,将上一个值赋给下一个
}
Data[i]=value;
index++;
return true;
}
删除
// c语言实现 复杂度O(n)
int deleteData(int i,List list){int j;
if(i>list->index||i<0||list->index<0){
printf("位置出错或咩有元素");
return 0;
}
for(j=i;j<list->index;++j){
list->Data[j]=list->Data[j+1];
}
list->--;
return 1;
}
// java实现
boolean delete(int i){if(isEmpty()||i>index||i<0){
return false;//为空或者位置不合法
for(int j=i;j<index;++j){
Data[j]=Data[j+1];
//从删除的位置开始,下一个的值赋给上一个。
}
index--;
return true;
}
C语言实现的另一种写法
#include <stdlib.h>
#include <iostream>
#define MAXSIZE 100
using namespace std;
typedef int ElemType;
typedef struct Node{
ElemType *elem;
int index;
}*ArrList;
void makeList(ArrList list);
int size(ArrList list);
ElemType get(int i,ArrList list);
void set(int i,int value,ArrList list);
int insert(int i,int value,ArrList list);
int deletes(int i,ArrList list);
int main(){
}
void makeList(ArrList list){
list->elem=new ElemType[MAXSIZE];
if(!list->elem) return NULL;
list->index=0;
}
int size(ArrList list){
if(!list) return 0;
return list->index;
}
ElemType get(int i,ArrList list){
if(i<=0||i>list->index) return -1;
return list->elem[i];
}
void set(int i,ElemType value,ArrList list){
if(i<=0||i>list->index) return ;
list->elem[i]=value;
}
int insert(int i,ElemType value,ArrList list){
int j;
if(list->index==MAXSIZE) return -1; //线性表已满,无法插入
if(i<=0||i>list->index+1) return -1; //位置越界
for(j=list->index;j>=i;--j){
list->elem[j+1]=list->elem[j];
}
list->elem[i]=value;
list->index++;
return 1;
}
int deletes(int i,ArrList list){
int j;
if(i<=0||i>list->index) return -1;
for(j=i;j<list->index;++j){
list->elem[j]=list->elem[j+1];
}
list->index--;
return 1;
}
2.3 线性表实现 (链表实现)
- 链表的特点:
- 逻辑上相邻的数据元素在物理上不一定相邻
- 访问时只能通过头指针进入链表,并通过每个结点的指针域向后扫描其余结点。
- 数据元素的个数可以自由扩充
- 插入、删除等操作不必移动数据,只需修改链接指针
存储密度小,
存取效率不高,必须采用顺序存取,即存取数据元素时,只能按链表的顺序进行访问- 三个概念(头指针,头结点,首结点):
头指针:是指向链表中第一个结点的指针。
头结点: 是一个链表的开头,头结点的数据域可以为空,也可存放线性表长度等附加信息,但此结点不能计入链表长度值。(可有可无)
首结点:链表真正存储数据的第一个结点。 分类:单链表,循环链表,双向链表等
- 单链表: 单链表中每一个结点由数据域和指针域构成,成一条链,(只能访问后继结点不能访问前趋结点)
链表结束的条件:link->next==NULL;
- 单链表: 单链表中每一个结点由数据域和指针域构成,成一条链,(只能访问后继结点不能访问前趋结点)
//定义
struct LinkedList{ElemType data;
struct LinkList *next;
}
//或者
typedef struct LinkedList{Elemtype data;
Linked next;
}*Linked;
- 三个概念(头指针,头结点,首结点):
循环链表:分为单循环链表和双循环链表,
单循环链表与单链表类似,让最后结点的指针域指头结点。
对循环链表,有时不给出头指针,而给出尾指针可以更方便的找到第一个和最后一个结点
定义与单链表或者双向链表一致,只需要最后结点指向头结点即可
结束条件判断:link->next!=info;(不等于头结点或者是首结点)
双向链表:一个结点中有两个指针域一个数据域,指针域分别指向下一个结点和上一个结点。
//定义
typedef struct DuLNode{
ElemType data;
struct DuLNode *prior;
struct DuLNode *next;
}DuLNode, *DuLinkList
如图:
线性表单链表代码实现
//宏定义
#define OK 1
#define ERROR 0
#define OVERFLOW -2
//定义
typedef int ElemType;
typedef int Status;
typedef struct LinkedList *Link;
struct LinkedList{
ElemType data;
Link next;
};
//方法体
Link CreateInputLinked(int n);
int size(Link link);
Link get(Link link,int i);
void set(Link link,int i,ElemType value);
Status insert(Link link,int i,ElemType value);
Status drop(Link link,int i);
void OutputLink(Link link);
Status DestroyList(Link link);
int main(){
return 0;};
//初始化加输入
Link CreateInputLinked(int n){
Link head,temp,node,info;
head = new LinkedList;
info = new LinkedList;
head->next=info;
info->next = NULL;
temp = info;
while(n-->0){
node = new LinkedList;
cin>>node->data;
node->next=NULL;
temp->next=node;
temp=temp->next;
}
return head;
}
//取长度
int size(Link link){
Link temp = link->next->next;
int count=0;
while(temp){
count++;
temp = temp->next;
}
return count;
}
// 获得第i个结点
Link get(Link link,int i){
Link temp = link->next->next;
int count = 1;
while(temp&&count<i){
temp = temp->next;
count++;
}
return count==i ? temp : NULL;
}
//修改第i个结点的数据域
void set(Link link,int i,ElemType value){
Link temp = link->next->next;
int count = 1;
while(temp&&count<i){
temp = temp->next;
count++;
}
if(count==i) temp->data=value;
}
//插入操作
Status insert(Link link,int i,ElemType value){
Link left,node;
if(i==1){
left = link->next;
}else{
left = get(link,i-1);
}
if(!left) return ERROR;
node = new LinkedList;
node->data=value;
node->next = left->next;
left->next = node;
return OK;
}
//删除操作
Status drop(Link link,int i){
Link left,mid;
if(i==1){
left =link->next;
}else{
left = get(link,i-1);
}
if(!left) return ERROR;
mid = left->next;
left->next=mid->next;
delete mid;
return OK;
}
//输出操作
void OutputLink(Link link){
Link temp = link->next->next;
while(temp){
cout<<temp->data<<" ";
temp=temp->next;
}
cout<<endl;
}
//销毁
Status DestroyList(Link link){
Link tmp;
while(link){
tmp=link;
link=link->next;
delete tmp;
}
return OK;
}
java实现(java只要理解到this本身就是头指针,并且在使用时先初始化再取得当前对象的next,才不会出现NullPointerExpetion,与C语言略微不同)
class NodeList{
int Data;
NodeList Next ;
boolean isEmpty(){
//判断是否为空
if(this.Next==null) return true;
return false;
}
int size(){
// 取长度
NodeList link=this.Next.Next;
if(this.isEmpty()) return 0;
int i=0;
while(link!=null){
link=link.Next;
i++;
}
return i;
}
NodeList getValue(int i){
//获取第i个结点
if(i>size()||i<0) return null;
NodeList link =this.Next;
int p = 0;
while(p<i&&link!=null){
link=link.Next;
++p;
}
if(p==i) return link;
else return null;
}
void setValue(int i,int value){
// 修改第i个值
NodeList tmp = getValue(i);
if(tmp==null) return;
tmp.Data=value;
}
boolean insert(int i,int value){
//插入一个新结点
if(i<0&&i>size()+1) return false;
NodeList left;
if(i==1){
left = this.Next;
}else {
left = getValue(i-1);
}
if(left==null) return false;
NodeList tmp = new NodeList();
tmp.Data=value;
tmp.Next=left.Next;
left.Next=tmp;
return true;
}
boolean delete(int i){
//删除一个结点
if(i<0||i>size()) return false;
NodeList left;
if(i==1){
left = this;
}else {
left = getValue(i-1);
}
if(left==null) return false;
NodeList tmp =left.Next;
left.Next = tmp.Next;
return true;
}
void Output(){
//输出,因为this代表头指针,要两次next才能找到首结点,中间隔了一个头结点
NodeList link = this.Next.Next;
while(link!=null){
System.out.print(link.Data+" ");
link=link.Next;
}
System.out.println();
}
void Input(int n){
// 输入操作,先初始化再赋值给结点.next,避免空指针异常
Scanner input =new Scanner(System.in);
NodeList link =new NodeList();
this.Next=link;
while(n-->0){
NodeList node =new NodeList();
node.Data=input.nextInt();
link.Next=node;
link=link.Next;
}
}
}
还没有评论,来说两句吧...