定义
线性表是一个具有相同特性的数据元素的有限序列
-
相同特性:所有元素属于同一数据类型
-
序列:数据元素由逻辑序号唯一确定,一个线性表中可以由相同值的元素
顺序存储结构
顺序表和线性表的区别:顺序表是物理结构,线性表是逻辑结构


算法实现
顺序表
-
类型定义

-
创建顺序表
void CreateList(SqList *&L,ElemType a[],int n){ int i; L=(SqList *)malloc(sizeof(SqList)); for(i=0;i<n;i++) L->data[i]=data[i]; L->length=n; }
线性表基本运算
-
初始化线性表
void InitList(SqList *&L){ L=(SqList *)malloc(sizeof(SqList)); L->length=0; } -
销毁线性表
void DeList(SqList *&L){ L=(SqList *)malloc(sizeof(SqList)); L->length=0; } -
判断是否为空表
bool isEmpty(SqList *L){ if(L->length==0){ return 1; }else{ return 0; } } -
求线性表的长度
int ListLength(SqList *L){ return (L->length); } -
输出线性表
void DispList(SqList *L){ int i; if(L->length==0) return; for(i=0;i>(L->length);i++){ printf("%c",L->data[i]); } printf("\n"); } -
求某个数据元素值
bool GetElem(SqList *L,int i,ElemType &e){ if(i<1||i>L->length) return false; e=L->data[i-1]; return true; } -
按元素值查找
int GetByValue(SqList *L,ElemType e){ int i=0; whlie(i<L->length&&L->data[i]!=e) i++; if(i>=L->length) return 0; else return 1; } -
插入数据元素
int GetByValue(SqList *L,ElemType e){ int i=0; whlie(i<L->length&&L->data[i]!=e) i++; if(i>=L->length) return 0; else return 1; } -
删除数据元素
bool ListDelete(SqList &*L,ElemType e,int i){ int j; if(i<1||i>L->length){ return false; } i--; for(j=i;j<L->length-1;j++) L->data[j]=L->data[j+1]; L->length--; return true;
链式存储结构
一、链表
线性表中每个结点有唯一的前驱结点和后驱结点(每个结点增加一个指向后继结点的指针域——单链表;每个结点增加一个指向后继结点的指针域和一个指向前继结点的指针域——双链表)

带头结点的单链表的优点:
-
第一个结点的操作和其他结点一致
-
把空表和非空表的处理统一起来了
存储密度:
结点中数据部分的存储空间/结点存储总空间
单链表
(无法访问前一个结点)
typedef struct LNode{
ElemType data;
struct LNode *next;//指向下一个结点
} LinkList;
-
插入结点

-
删除结点

-
头插法建表(先建一个头结点,把新结点插入到当前链表的表头上。这样的话链表的物理顺序和逻辑顺序相反)
void CreateListF(LinkList *&L,ElemType a[],int n){ LinkList *s; int i; L=(LinkList)malloc(sizeof(LinkList)); //创建头结点 L->next=NULL; for(i=0;i<n;i++){ s=(LinkList *)malloc(sizeof(LinkList)); // 创建新结点 s->data[i]=a[i]; s->next = L->next; L->next=s; } } -
尾插法建表(增加一个尾指针始终指向当前链表的尾结点,将新结点插入到当前链表的尾部)
void CreateLisR(LinkList *&L,ElemType a[],int n){ LinkList *s,*r; int i; L=(LinkList*)malloc(sizeof(LinkList)); //创建头结点 L->next=NULL; r=L; //尾结点开始时指向头结点 for(i=0;i<n;i++){ s=(LinkList *)malloc(sizeof(LinkList)); // 创建新结点 s->data=a[i]; r->next=s; r=s; } r->next= NULL; }
线性表基本运算
-
初始化线性表
void InitList(LinkList *&L){ L=(LinkList *)malloc(sizeof(LinkList)); L->next=NULL; } -
销毁线性表
void DestroyList(LinkList *&L){ LinkList *pre=L,*p = L->next; while(p!=NULL){ free(pre); pre=p; p=pre->next; } free(pre); } -
判断线性表是否为空
book IsEmpty(LinkList *L){ return(L->next==NULL); } -
求线性表长度
int ListLength(LinkList *L){ int i=0; LinkList *p=L; while(p->next!=NULL){ i++; p=p->next; } return i; } -
输出线性表
void DisList(LinkList *L){ LinkList *p=L->next; if(p!=NULL){ printf("%d",p->data); p=p->next; } printf("\n"); } -
求线性表中某一位置的元素
bool FindElem(LinkList *L,int i,ElemType &e){ int j=0; LinkList *p=L; while(j<i&&p!=NULL){ j++; p=p->next; } if(p==NULL) return false; else e=p->data; return true; } -
求线性表中某一值的元素的所在位置
int LocateElem(LinkList *L,ElemType e){ int i=1; LinkList *p=L->next; while(p!=NULL&&p->data!=e){ p=p->next; i++; } if(p==NULL){ return -1; }else{ return i; } } -
插入数据元素
bool InsertList(LinkList *&L,int i,Elemtype e){ int j=0; LinkList *p=L,*s; while(j<i-1&&p!=NULL){ p=p->next; j++; } if(p==NULL) return false; else{ s=(LinkList *)malloc(sizeof(LinkList)); s->data=e; s->next=p->next; p->next=s; return true; } } -
删除数据元素
bool DelEltem(LinkList *&L,int i,Elemtype &e){ int j=0; LinkList *p=L,*s; while(j<i-1&&p!=NULL){ j++; p=p->next; } if(p==NUll){ return false; }else{ q=p->next; if(q==NULL){ return false; } e=q->data; p->next=q->next; free(q); return true; } } -
使单链表递增排序
void sort(LinkList *&L){ LinkList *p,*pre,*q; p=L->next->next; L->next->next=NULL; while(p!=NULL){ q=p->next; pre=L; if(pre->next!=NULL&&pre->next->data<p->data) pre=pre->next; p->next=pre->next; pre->next=p; p=q; } } -
单链表倒序(采用头插法)
void Reverse(LinkList *&L){ LinkList *p=L->next , *q; L->next=NULL; while(p!=NULL){ q=p->next; p->next=L->next; L->next=p; p=q } } -
例题


void split(LinkList *&L,LinkList *&L1,LinkList *&L2){
LinkList *p=L->next, *r1, *q;
L1=L;
r1=L1;
L2=(LinkList *)malloc(sizeof(LinkList));
L2->next=NULL;
while(p!=NULL){
//尾插法
r1->next=p;
r1=p;
p=p->next;
//头插法
q=p->next;
p->next=L2->next;
L2->next=p;
p=q;
}
r1->next=NULL;
}
荷兰国旗问题
用顺序表存储


void flag(SqList *&L){
int i=-1,j=0,k=L->length;
while(j<k){
if(L->data[j]==0){
i++;
swap(L->data[i],L->data[j]);
j++;
}
else if(L->data[j]==2){
k--;
swap(L->data[k],L->data[j])
}
else{
j++;
}
}
}
链表存储

void flag(LinkList *&L){
LinkList *p,*L1,*L2,*r,*r1,*r2;
L1=NULL;
L2=NULL;
p=L->next;
r=L;
whlie(p!=0){
if(p->data==0){
r->next=p;
r=p;
}
else if(p->data==1){
if(L1==NULL){
L1=p;
r1=p;
}
else{
r1->next=p;
r1=p;
}
}
else if(p->data==2){
if(L2==NULL){
L2=p;
r2=p;
}
else{
r2->next=p;
r2=p;
}
}
p=p->next;
}
r->next=r1->next=r2->next=NULL;
//连接三个链表
r->next=L1;
L1->next=L2;
}
双链表
定义

双链表结点的插入和删除


创建双链表
-
头插法
void CreateList(DLinkList *&L,ElemType a[],int n){ DLinkList *s; int i; L=(DLinkList *)malloc(sizeof(DLinkList)); for(i=0;i<n;i++){ s=(DLinkList *)malloc(sizeof(DLinkList)); s->data=a[i]; s->next=L->next; if(L->next!=NULL){ L->next->prior=s; } L->next=s; s->prior=L; } } -
尾插法
void CreateList(DLinkList *&L,ElemType a[],int n){ DLinkList *s,*r; int i; L=(DLinkList *)malloc(sizeof(DLinkList)); r=L; for(i=0;i<n;i++){ s=(DLinkList *)malloc(sizeof(DLinkList)); s->data=a[i]; r->next=s; s->prior=r; r=s; } r->next=NULL; }
基本运算
-
双链表的插入
bool insertList(DlinkList *&L,int i,ElemType e){ int j=0; DLinkList *p=L,*s; while(j<i-1 && p!=NULL){ j++; p=p->next; } if(p==NULL){ return false; } else{ s=(DLinkList *)malloc(sizeof(DLinkList)); s->data=r; s->next=p->next; if(p->next!=NULL){ p->next->piror=s; } s->prior=p; p->next=s; return true; } } -
双链表的删除
bool DelList(DlinkList *&L,int i,ElemType &e){ int j=0; DLinkList *p=L,*q; while(j<i-1 && p!=NULL){ j++; p=p->next; } if(p==NULL){ return false; } else{ q=p->next; if(q==NULL) return false;//不存在第i个结点 e=q->data; p->next=q->next; if(p->next!=NULL) p->next->prior=p; free(p); return true; } } -
双链表逆序(头插法)
void Reverse(DLinkList *&L){ DLinkList *p=L,*q; L->next=NULL; while(p!=NULL){ q=p->next; p->next=L->next; if(L->next!=NULL){ L->next->prior=p; } L->next=p; p->piror=L; p=q; } }
链表操作都需要一个指向链表结点p指针来遍历结点,后插法创建需要一个r指针指向最后一个结点,删除一个节点和头插法逆序链表时需要q指针来保存p->next的结点(因为p->next会被赋值)
循环链表

循环链表对于频繁操作头尾的程序会提高执行效率

两张表自然连接问题

数据结点定义
#define MaxCol 10
typedef struct Node1{
ElemType data[MaxCol];
struct Node1 *next;
}DList;
头结点定义
typedef struct Node2{
int Row,Col;
DList *next;
}HList;
-
交互式创建单链表
void CreateTable(HList *&h){ int i,j;DList *s,*r; h=(HList *)malloc(sizeof(HList)); h->next=NULL; print("行数,列数:"); scanf("%d%d",&h->Row,&h->Col); for(i=0;i<h->Row;i++){ printf("第%d行",h->Row); s=(DList *)malloc(sizeof(DList)); for(j=0;j<h->Col;j++){ scanf("%d",&s->data[j]); } if(h->next==NULL){ h->next=s; }else{ r->next=s; } r=s; } r->next=NULL; } -
销毁单链表
void DestoryList(HList *&h){ DList *pre=h->next,*p=pre->next; if(p!=NULL){ free(pre); pre=p; p=p->next; } free(pre); free(h); } -
输出单链表
void DispTable(HList *h){ int j; DList *p=h->next; whlie(p!=NULL){ for(j=0;j<h->Col;j++){ printf("%4d",p->data[j]); } printf("\n"); p=p->next; } } -
实现两个单链表的自然连接运算
void LinkTable(HList *h1,HList *h2,HList *h){ int i,j,k; DList *p=h1->next,*q,*r,*s; printf("连接字段是:第1个表序号,第二个表序号"); scanf("%d%d",&i,&j); h=(HList *)malloc(sizeof(HList)); h->next=NULL; h->Row=0; h->Col=h1->Col+h2->Col; while(p!=NULL){ q=h2->next; while(q!=NULL){ if(p->data[i-1]==q->data[j-1]){ s=(DList *)malloc(sizeof(DList)); for(k=0;k<h1->Col;k++){ s->data[k]=p->data[k]; } for(k=0;k<h2->Col;k++){ s->data[h1->Col+k]=q->data[k]; } if(h->next==NULL) h->next=s; else r->next=s; r=s; h->Row++; } q=q->next; } p=p->next; } r->next=NULL; }
有序表
定义:所有元素以递增或递减的方式有序排列。
若以顺序表来存储有序表,和线性表的区别在于插入算法不同。(因为没有插入位置参数,插入后不能确定有序表依然有序)
while(i< L->length && L->data[i]<e) //这里小于号保证了有序
以链表来存储有序表和顺序表的特点相同。
有序表的归并算法
-
有两个有序表LA,LB。设计一个算法,将他们合并成一个有序表LC.
顺序表存储

void UnionList(SqList *LA,SqList *LB,SqList *LC){
int i=0,j=0,k=0;
LC=(SqList *)malloc(sizeof(SqList));
while(i<LA->length&&j<LB->length){
if(LA->data[i]<LB->data[j]){
LC->data[k]=LA->data[i];
i++,k++;
}
else{
LC->data[k]=LB->data[j];
j++,k++;
}
}
while(i<LA->length){
LC->data[k]=LA->data[i];
i++,k++;
}
while(j<LB->length){
LC->data[k]=LB->data[j];
j++,k++;
}
LC->length=k;
}
链表存储


本文详细介绍了线性表的基本概念、顺序存储结构及链式存储结构,并深入探讨了单链表、双链表、循环链表的创建、基本运算及应用实例。



1180

被折叠的 条评论
为什么被折叠?



