一、从数据结构的三要素了解线性表
1、逻辑结构
定义:线性表是具有相同数据类型的n(n>=0)个数据元素的有限序列
特点:除第一个元素外,每个元素有且仅有一个直接前趋,除最后一个元素外,每个元素有且仅有一个直接后继
线性表是一种逻辑结构
2、数据的运算
数据的运算即是对数据结构的操作集
以下通过抽象数据类型描述体现线性表
抽象数据类型描述
(参考中国大学mooc浙江大学数据结构)
3、存储结构
顺序表——顺序存储实现
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 5
#define ERROR -1
typedef enum {false, true} bool;
typedef int ElementType;
typedef int Position;
typedef struct LNode *List;//定义一个指向结构体struct LNode的指针变量
struct LNode {
ElementType Data[MAXSIZE];
Position Last;//表示最后一个元素
};
/* 初始化 */
List MakeEmpty()
{
List L;
L = (List)malloc(sizeof(struct LNode));//将该内存空间首地址转换为list结构体指针类型
L->Last = -1;//->相当于java中某个方法中引用成员变量 即L.last
return L;
}
/* 查找 */
Position Find( List L, ElementType X )
{
Position i = 0;
while( i <= L->Last && L->Data[i]!= X )
i++;
if ( i > L->Last ) return ERROR; /* 如果没找到,返回错误信息 */
else return i; /* 找到后返回的是存储位置 */
}
/* 插入 */
/*注意:在插入位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Insert( List L, ElementType X, Position P )
{ /* 在L的指定位置P前插入一个新元素X */
Position i;
if ( L->Last == MAXSIZE-1) {
/* 表空间已满,不能插入 */
printf("表满");
return false;
}
if ( P<0 || P>L->Last+1 ) { /* 检查插入位置的合法性 */
printf("位置不合法");
return false;
}
for( i=L->Last; i>=P; i-- )//从最后一个元素往前 ,如果是从前往后挪,后面的元素会被前一个元素覆盖
L->Data[i+1] = L->Data[i]; /* 将位置P及以后的元素顺序向后移动 */
L->Data[P] = X; /* 新元素插入 */
L->Last++; /* Last仍指向最后元素 */
return true;
}
/* 删除 */
/*注意:在删除位置参数P上与课程视频有所不同,课程视频中i是序列位序(从1开始),这里P是存储下标位置(从0开始),两者差1*/
bool Delete( List L, Position P )
{ /* 从L中删除指定位置P的元素 */
Position i;
if( P<0 || P>L->Last ) { /* 检查空表及删除位置的合法性 */
printf("位置%d不存在元素", P );
return false;
}
for( i=P+1; i<=L->Last; i++ )
L->Data[i-1] = L->Data[i]; /* 将位置P+1及以后的元素顺序向前移动 */
L->Last--; /* Last仍指向最后元素 */
return true;
}
int main()
{
List L;
ElementType X;
Position P;
int N;
L = MakeEmpty();//初始化顺序表
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
if ( Insert(L, X, 0)==false )
printf(" Insertion Error: %d is not in.\n", X);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else
printf("%d is at position %d.\n", X, P);
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &P);
if ( Delete(L, P)==false )
printf(" Deletion Error.\n");
if ( Insert(L, 0, P)==false )
printf(" Insertion Error: 0 is not in.\n");
}
return 0;
}
输入样例:
6
1 2 3 4 5 6
3
6 5 1
2
-1 6
输出结果:
链表——链式存储实现
不带头结点的链式表操作集
题源:PTA 数据结构与算法题目集(中文)6-5
#include<stdio.h>
#include<stdlib.h>
#define ERROR NULL
typedef int ElementType;
typedef struct LNode *PtrTolNode;
struct LNode{
ElementType Data;
PtrTolNode Next;//指向下一个
};
typedef PtrTolNode Position;
typedef PtrTolNode List;
//查找值为X的元素 (返回线性表中首次出现X的位置,若找不到则返回ERROR)
Position Find(List L,ElementType X){
Position p=L;//p指向L的第一个结点
while(p&&p->Data!=X){
p=p->Next;
}
if(p){
return p;
}else{
return ERROR;
}
}
/*
*不带头结点的插入
*将X插入在位置P指向的结点之前,返回链表的表头
*如果参数P指向非法位置,则打印"Wrong Position for Insertion" 返回ERROR
*/
List Insert(List L,ElementType X,Position P){
if(P==L){
List Node = (List)malloc(sizeof(List));
Node->Data=X;
Node->Next=L;
return Node;
}
Position pre,tmp;
//查找P的前驱
for(pre=L;pre&&pre->Next!=P;pre=pre->Next);
if(pre==NULL){//P所指结点不在L中
printf("Wrong Position for Insertion\n");
return ERROR;
}else{//找到了P所指结点前驱
tmp=(Position)malloc(sizeof(struct LNode));//申请、填装结点
tmp->Data=X;
/*
修改前:
tmp->Next=pre->Next;
pre->Next=tmp->Next;*/
//修改后
tmp->Next = P;
pre->Next = tmp;
return L;
}
}
/*
不带头结点的删除
将X插入在位置P指向的结点之前,返回链表的表头
若参数P指向非法位置,则打印"Wrong Position for Deletion"并返回ERROR
*/
List Delete(List L,Position P){
if(P==L){
L=L->Next;
return L;
}
Position pre;
//查找表中P指向结点的前驱
for(pre=L;pre&&pre->Next!=P;pre=pre->Next);
if(pre==NULL){
printf("Wrong Position for Deletion\n");
return ERROR;
}else{
pre->Next=P->Next;
free(P);
return L;
}
}
int main()
{
List L;
ElementType X;
Position P, tmp;
int N;
L = NULL;
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
L = Insert(L, X, L);
if ( L==ERROR ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
L = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( L==ERROR )
printf("Wrong Answer or Empty List.\n");
}
}
L = Insert(L, X, NULL);
if ( L==ERROR ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
tmp = Insert(L, X, P);
if ( tmp!=ERROR ) printf("Wrong Answer\n");
tmp = Delete(L, P);
if ( tmp!=ERROR ) printf("Wrong Answer\n");
for ( P=L; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
输入样例:
6
12 2 4 87 10 2
4
2 12 87 5
结果:
2 is found and deleted.
12 is found and deleted.
87 is found and deleted.
Finding Error: 5 is not in.
5 is inserted as the last element.
Wrong Position for Insertion
Wrong Position for Deletion
10 4 2 5
带头结点的链式表操作集
题源:PTA数据结构与算法题目集(中文)6-6
#include <stdio.h>
#include <stdlib.h>
#define ERROR NULL
typedef enum {false, true} bool;
typedef int ElementType;
typedef struct LNode *PtrToLNode;
struct LNode {
ElementType Data;
PtrToLNode Next;
};
typedef PtrToLNode Position;
typedef PtrToLNode List;
List MakeEmpty(){
/*
创建并返回一个空的线性表;
*/
List L;
L=(List)malloc(sizeof(struct LNode));
L->Next=NULL;
return L;
}
Position Find( List L, ElementType X ){
/*
返回线性表中X的位置。若找不到则返回ERROR
*/
Position p=L->Next;//第一个结点
while(p!=NULL){
if(p->Data==X) return p;
p=p->Next;
}
return ERROR;
}
bool Insert( List L, ElementType X, Position P ){
/*
将X插入在位置P指向的结点之前,返回true。
如果参数P指向非法位置,则打印“Wrong Position for Insertion”,返回false
*/
Position tmp,pre;
for(pre=L;pre&&pre->Next!=P;pre=pre->Next);//找p的前驱
if(pre==NULL){
printf("Wrong Position for Insertion\n");
return false;
}
else{
tmp=(Position)malloc(sizeof(struct LNode));//分配新的空间给新的结点
tmp->Data=X;
tmp->Next=P;
pre->Next=tmp;
return true;
}
}
bool Delete( List L, Position P ){
/*
将位置P的元素删除并返回true。
若参数P指向非法位置,则打印“Wrong Position for Deletion”并返回false。
*/
Position pre;
for(pre=L;pre&&pre->Next!=P;pre=pre->Next);//找p的前驱
if(pre==NULL){
printf("Wrong Position for Deletion\n");
return false;
}
else{
pre->Next=P->Next;
free(P);//释放结点P的空间
return true;
}
}
int main()
{
List L;
ElementType X;
Position P;
int N;
bool flag;
L = MakeEmpty();
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
flag = Insert(L, X, L->Next);
if ( flag==false ) printf("Wrong Answer\n");
}
scanf("%d", &N);
while ( N-- ) {
scanf("%d", &X);
P = Find(L, X);
if ( P == ERROR )
printf("Finding Error: %d is not in.\n", X);
else {
flag = Delete(L, P);
printf("%d is found and deleted.\n", X);
if ( flag==false )
printf("Wrong Answer.\n");
}
}
flag = Insert(L, X, NULL);
if ( flag==false ) printf("Wrong Answer\n");
else
printf("%d is inserted as the last element.\n", X);
P = (Position)malloc(sizeof(struct LNode));
flag = Insert(L, X, P);
if ( flag==true ) printf("Wrong Answer\n");
flag = Delete(L, P);
if ( flag==true ) printf("Wrong Answer\n");
for ( P=L->Next; P; P = P->Next ) printf("%d ", P->Data);
return 0;
}
输入样例
6
12 2 4 87 10 2
4
2 12 87 5
输出结果
2 is found and deleted.
12 is found and deleted.
87 is found and deleted.
Finding Error: 5 is not in.
5 is inserted as the last element.
Wrong Position for Insertion
Wrong Position for Deletion
10 4 2 5