王道学习
考纲内容
(一)线性表的基本概念
(二)线性表的实现
顺序存储;链式存储
(三)线性表的应用
知识框架
复习提示
线性表是算法题命题的重点。这类算法题的实现比较容易且代码量较少,但是要求具有最优的性能(时间/空间复杂度),才能获得满分。因此,应牢固掌握线性表的各种基本操作(基于两种存储结构),在平时的学习中多注重培养动手能力。另需提醒的是,算法最重要的是思想!考场上的时间紧迫,在试卷上不一定要求代码具有实际的可执行性,因此应尽力表达出算法的思想和步骤,而不必拘泥所有细节。此外,采用时间/空间复杂度较差的方法也能拿到大部分分数,因此在时间紧迫的情况下,建议直接采用暴力法。注意,算法题只能用C/C++语言实现。
2.1 线性表的定义和基本操作
2.1.1 线性表的定义
由此,我们得出线性表的特点如下:
- 表中元素的个数有限。
- 表中元素具有逻辑上的顺序性,表中元素有其先后次序。
- 表中元素都是数据元素,每个元素都是单个元素。
- 表中元素的数据类型都相同,这意味着每个元素占有相同大小的存储空间。
- 表中元素具有抽象性,即仅讨论元素间的逻辑关系,而不考虑元素究竟表示什么内容。
注意:线性表是一种逻辑结构,表示元素之间一对一的相邻关系。顺序表和链表是指存储结构,两者属于不同层面的概念,因此不要将其混淆。
2.1.2 线性表的基本操作
2.1.3 本节试题精选
以下()是一个线性表。
A. 由n个实数组成的集合
B. 由100个字符组成的序列
C. 所有整数组成的序列
D. 邻接表
答案:B
线性表定义的要求为:相同数据类型、有限序列。选项C的元素个数是无穷个,错误;选项A集合中的元素没有前后驱关系,错误;选项D属于存储结构
2.2 线性表的顺序表示
2.2.1 顺序表的定义
顺序表–用顺序存储的方式实现线性表
顺序存储。把逻辑上相邻的元素存储在物理位置上也相邻的存储单元中,元素之间的关系由存储单元的邻接关系来体现。
注意:线性表中元素的位序是从1开始的,而数组元素的下标是从0开始的
注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构没有变化,依然是随机存取方式,只是分配的空间大小可以在运行时动态决定。
顺序表的主要优点:(1)可进行随机访问,即可通过首地址和元素序号可以在O(1)时间内找到指定的元素;(2)存储密度高,每个结点只存储数据元素。顺序表的缺点也很明显:(1)元素的插入和删除需要移动大量的元素,插入操作平均需要移动n/2个元素,删除操作平均需要移动(n-1)/2个元素;(2)顺序存储分配需要一段连续的存储空间,不够灵活。
2.2.2 顺序表的实现
2.2.2.1 顺序表的实现–静态分配
#include <stdio.h>
#define MAXSIZE 10
struct SqList{
//顺序表
int data[MAXSIZE];
//顺序表长度
int length;
};
typedef struct SqList SqList;
/*
初始化顺序表
*/
void initList(SqList *list){
int i=0;
//初始化顺序表的长度为5
(*list).length=5;
//向顺序表中插入5个元素
for(;i<5;i++){
(*list).data[i]=i+1;
}
}
/*
插入:向顺序表中指定位置插入元素
SqList *list:顺序表
int index:位置
int element:元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int insertList(SqList *list,int index,int element){
int tmp=(*list).length-1;
int i=index-1;
//如果插入位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//判断顺序表的空间是否已满
if((*list).length>=sizeof((*list).data)/sizeof(int)){
return 0;
}
//插入元素
for(;tmp>=i;tmp--){
(*list).data[tmp+1]=(*list).data[tmp];
}
(*list).data[i]=element;
(*list).length=(*list).length+1;
return 1;
}
/*
删除:顺序表删除指定位置的元素
SqList *list:顺序表
int index:位置
int *element:被删除的元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int deleteList(SqList *list,int index,int *element){
int tmp=(*list).length-1;
int i=index-1;
//如果删除位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//如果删除位置小于1,返回0
if(index<1){
return 0;
}
*element=(*list).data[index-1];
//删除元素
for(;i<=tmp;i++){
(*list).data[i]=(*list).data[i+1];
}
(*list).length=tmp;
return 1;
}
/*
按位查找:通过位置返回顺序表的的元素
SqList list:顺序表
int index:位置
返回一个int型变量:
index位置上的元素
*/
int getElementByIndex(SqList *list,int index){
return (*list).data[index-1];
}
/*
按值查找:
SqList list:顺序表
int element:元素
返回一个int型变量:
index位置:返回-1 说明顺序表没有此元素
*/
int getIndexByElement(SqList *list,int element){
int i=0;
int index=-1;
for(;i<(*list).length;i++){
if((*list).data[i]==element){
index=i+1;
break;
}
}
return index;
}
int main(){
SqList list;
int i=0;
int j=0;
int element=0;
initList(&list);
insertList(&list,3,8);
deleteList(&list,3,&element);
for(;j<list.length;j++){
printf("%d",list.data[j]);
}
return 0;
}
#include <stdio.h>
#define MAXSIZE 10
struct SqList{
int data[MAXSIZE];
int length;
};
typedef struct SqList SqList;
void initList(SqList *list){
int i=0;
list->length=5;
for(;i<5;i++){
list->data[i]=i+1;
}
}
int insertList(SqList *list,int index,int element){
int tmp=list->length-1;
int i=index-1;
if(index>list->length){
return 0;
}
if(list->length>=sizeof(list->data)/sizeof(int)){
return 0;
}
for(;tmp>=i;tmp--){
list->data[tmp+1]=list->data[tmp];
}
list->data[i]=element;
list->length=list->length+1;
return 1;
}
int deleteList(SqList *list,int index,int *element){
int tmp=list->length-1;
int i=index-1;
if(index>list->length){
return 0;
}
if(index<1){
return 0;
}
*element=list->data[i];
for(;i<=tmp;i++){
list->data[i]=list->data[i+1];
}
list->length=tmp;
return 1;
}
int getElementByIndex(SqList *list,int index){
return list->data[index-1];
}
int getIndexByElement(SqList *list,int element){
int i=0;
int index=-1;
for(;i<list->length;i++){
if(list->data[i]==element){
index=i+1;
break;
}
}
return index;
}
int main(){
SqList list;
int i=0;
int j=0;
int element=0;
initList(&list);
insertList(&list,3,8);
deleteList(&list,3,&element);
for(;j<list.length;j++){
printf("%d",list.data[j]);
}
return 0;
}
2.2.2.2 顺序表的实现–动态分配
注意:动态分配并不是链式存储,它同样属于顺序存储结构,物理结构并没有变化,依然是随机存储方式,只是分配的空间大小可以在运行时决定
#include <stdio.h>
#include <stdlib.h>
//顺序表的初始化长度
#define initSize 10
struct SeqList{
int *data;
//数组的最大容量
int maxSize;
//顺序表的长度
int length;
};
typedef struct SeqList SeqList;
/*
初始化顺序表:
最大容量为10
长度为5
顺序表元素为1到5
*/
void initList(SeqList *list){
int i=0;
//设置最大容量
(*list).maxSize=initSize;
//设置顺序表长度为5
(*list).length=initSize-5;
//为顺序表动态分配内存
(*list).data=(int *)malloc(sizeof(int)*initSize);
for(;i<(*list).length;i++){
(*list).data[i]=i+1;
}
}
/*
顺序表动态扩容:
SeqList *list:顺序表
int len:扩容长度
*/
void increaseSize(SeqList *list,int len){
int i=0;
int *tmp=(*list).data;
//最大容量扩容
(*list).maxSize=(*list).maxSize+len;
//重新为线性表动态分配内存
(*list).data=(int *)malloc(sizeof(int)*(*list).maxSize);
//原来元素迁移
for(;i<(*list).length;i++){
(*list).data[i]=tmp[i];
}
free(tmp);
}
/*
插入:向顺序表中指定位置插入元素
SeqList *list:顺序表
int index:位置
int element:元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int insertList(SeqList *list,int index,int element){
int tmp=(*list).length-1;
int i=index-1;
//如果插入位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//判断顺序表的空间是否已满
if((*list).length>=(*list).maxSize){
return 0;
}
//插入元素
for(;tmp>=i;tmp--){
(*list).data[tmp+1]=(*list).data[tmp];
}
(*list).data[i]=element;
(*list).length=(*list).length+1;
return 1;
}
/*
删除:顺序表删除指定位置的元素
SeqList *list:顺序表
int index:位置
int *element:被删除的元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int deleteList(SeqList *list,int index,int *element){
int tmp=(*list).length-1;
int i=index-1;
//如果删除位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//如果删除位置小于1,返回0
if(index<1){
return 0;
}
*element=(*list).data[index-1];
//删除元素
for(;i<=tmp;i++){
(*list).data[i]=(*list).data[i+1];
}
(*list).length=tmp;
return 1;
}
/*
按位查找:通过位置返回顺序表的的元素
SeqList list:顺序表
int index:位置
返回一个int型变量:
index位置上的元素
*/
int getElementByIndex(SeqList *list,int index){
return (*list).data[index-1];
}
/*
按值查找:
SeqList list:顺序表
int element:元素
返回一个int型变量:
index位置:返回-1 说明顺序表没有此元素
*/
int getIndexByElement(SeqList *list,int element){
int i=0;
int index=-1;
for(;i<(*list).length;i++){
if((*list).data[i]==element){
index=i+1;
break;
}
}
return index;
}
int main(){
SeqList list;
int i=0;
int j=0;
initList(&list);
insertList(&list,3,8);
deleteList(&list,3,&j);
for(;i<list.length;i++){
printf("%d",list.data[i]);
}
increaseSize(&list,5);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define initSize 10
struct SeqList{
int *data;
int maxSize;
int length;
};
typedef struct SeqList SeqList;
void initList(SeqList *list){
int i=0;
list->maxSize=initSize;
list->length=initSize-5;
list->data=(int *)malloc(sizeof(int)*initSize);
for(;i<list->length;i++){
list->data[i]=i+1;
}
}
void increaseSize(SeqList *list,int len){
int i=0;
int *tmp=list->data;
list->maxSize=list->maxSize+len;
list->data=(int *)malloc(sizeof(int)*(list->maxSize));
for(;i<list->length;i++){
list->data[i]=tmp[i];
}
free(tmp);
}
int insertList(SeqList *list,int index,int element){
int tmp=list->length-1;
int i=index-1;
if(index>list->length){
return 0;
}
if(list->length>=list->maxSize){
return 0;
}
for(;tmp>=i;tmp--){
list->data[tmp+1]=list->data[tmp];
}
list->data[i]=element;
list->length=list->length+1;
return 1;
}
int deleteList(SeqList *list,int index,int *element){
int tmp=list->length-1;
int i=index-1;
if(index>list->length){
return 0;
}
if(index<1){
return 0;
}
*element=list->data[i];
for(;i<=tmp;i++){
list->data[i]=list->data[i+1];
}
list->length=tmp;
return 1;
}
int getElementByIndex(SeqList *list,int index){
return list->data[index-1];
}
int getIndexByElement(SeqList *list,int element){
int i=0;
int index=-1;
for(;i<list->length;i++){
if(list->data[i]==element){
index=i+1;
break;
}
}
return index;
}
int main(){
SeqList list;
int i=0;
int j=0;
initList(&list);
insertList(&list,3,8);
deleteList(&list,3,&j);
for(;i<list.length;i++){
printf("%d",list.data[i]);
}
increaseSize(&list,5);
return 0;
}
2.2.3 本节试题精选
2.2.4 编程题练习
#include <stdio.h>
#include <stdlib.h>
//顺序表的初始化长度
#define initSize 10
struct SeqList{
int *data;
//数组的最大容量
int maxSize;
//顺序表的长度
int length;
};
typedef struct SeqList SeqList;
/*
初始化顺序表:
最大容量为10
长度为5
顺序表元素为1到5
*/
void initList(SeqList *list,int length){
int i=0;
//设置最大容量
(*list).maxSize=initSize;
//设置顺序表长度为5
(*list).length=length;
//为顺序表动态分配内存
(*list).data=(int *)malloc(sizeof(int)*initSize);
}
/*
顺序表动态扩容:
SeqList *list:顺序表
int len:扩容长度
*/
void increaseSize(SeqList *list,int len){
int i=0;
int *tmp=(*list).data;
//最大容量扩容
(*list).maxSize=(*list).maxSize+len;
//重新为线性表动态分配内存
(*list).data=(int *)malloc(sizeof(int)*(*list).maxSize);
//原来元素迁移
for(;i<(*list).length;i++){
(*list).data[i]=tmp[i];
}
free(tmp);
}
/*
插入:向顺序表中指定位置插入元素
SeqList *list:顺序表
int index:位置
int element:元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int insertList(SeqList *list,int index,int element){
int tmp=(*list).length-1;
int i=index-1;
//如果插入位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//判断顺序表的空间是否已满
if((*list).length>=(*list).maxSize){
return 0;
}
//插入元素
for(;tmp>=i;tmp--){
(*list).data[tmp+1]=(*list).data[tmp];
}
(*list).data[i]=element;
(*list).length=(*list).length+1;
return 1;
}
/*
删除:顺序表删除指定位置的元素
SeqList *list:顺序表
int index:位置
int *element:被删除的元素
返回一个int型变量:
1--插入成功
0--插入失败
*/
int deleteList(SeqList *list,int index,int *element){
int tmp=(*list).length-1;
int i=index-1;
//如果删除位置大于顺序表长度,返回0
if(index>(*list).length){
return 0;
}
//如果删除位置小于1,返回0
if(index<1){
return 0;
}
*element=(*list).data[index-1];
//删除元素
for(;i<=tmp;i++){
(*list).data[i]=(*list).data[i+1];
}
(*list).length=tmp;
return 1;
}
/*
按位查找:通过位置返回顺序表的的元素
SeqList list:顺序表
int index:位置
返回一个int型变量:
index位置上的元素
*/
int getElementByIndex(SeqList *list,int index){
return (*list).data[index-1];
}
/*
按值查找:
SeqList list:顺序表
int element:元素
返回一个int型变量:
index位置:返回-1 说明顺序表没有此元素
*/
int getIndexByElement(SeqList *list,int element){
int i=0;
int index=-1;
for(;i<(*list).length;i++){
if((*list).data[i]==element){
index=i+1;
break;
}
}
return index;
}
int main(){
int tempOne=0;
int tmepTwo=0;
int index=0;
int i=0;
int j=0;
SeqList firstList;
SeqList secondList;
SeqList cList;
initList(&firstList,4);
initList(&secondList,3);
firstList.data[0]=2;
firstList.data[1]=7;
firstList.data[2]=10;
firstList.data[3]=17;
secondList.data[0]=3;
secondList.data[1]=5;
secondList.data[2]=7;
// secondList.data[3]=12;
// secondList.data[4]=15;
for(;i<firstList.length;i++){
printf("%d ",firstList.data[i]);
}
printf("\n");
i=0;
for(;i<secondList.length;i++){
printf("%d ",secondList.data[i]);
}
printf("\n");
initList(&cList,firstList.length+secondList.length);
i=1;
j=1;
while(i<=firstList.length&&j<=secondList.length){
tempOne=getElementByIndex(&firstList,i);
tmepTwo=getElementByIndex(&secondList,j);
if(tempOne<=tmepTwo){
cList.data[index++]=tempOne;
i++;
}else{
cList.data[index++]=tmepTwo;
j++;
}
}
printf("%d ",i);
printf("\n");
printf("%d ",j);
printf("\n");
while (i<=firstList.length) {
cList.data[index++]=getElementByIndex(&firstList,i++);
}
while (j<=secondList.length) {
cList.data[index++]=getElementByIndex(&secondList,j++);
}
i=0;
for(;i<cList.length;i++){
printf("%d ",cList.data[i]);
}
return 0;
}
2.3 线性表的链式表示
顺序表可以随时存取表中的任意一个元素,它的存储位置可以用一个简单直观的公式表示,但插入和删除操作需要移动大量元素。链式存储线性表时,不需要使用地址连续的存储单元即不要求逻辑上相邻的元素在物理位置上也相邻,它通过“链”建立起数据元素之间的逻辑关系,因此插入和删除操作不需要移动元素,而只需修改指针,但也会失去顺序表可随机存取的优点。
2.3.1 单链表的定义
利用单链表可以解决顺序表需要大量连续存储单元的缺点,但单链表附加指针域,也存在浪费存储空间的缺点。由于单链表的元素离散地分布在存储空间中,所以单链表是非随机存取的存储结构,即不能直接找到表中某个特定的结点。查找某个特定的结点时,需要从表头开始遍历,依次查找。
头结点和头指针的关系:不管带不带头结点,头指针始终指向链表的第一个结点,而头结点是带头结点的链表中的第一个结点,结点内通常不存储信息。
引入头结点后,可以带来两个优点:
(1)由于第一个数据结点的位置被存放在头结点的指针域中,所以在链表的第一个位置上的操作和在表的其他位置上的操作一致,无须进行特殊处理。
(2)无论链表是否为空,其头指针都指向头结点的非空指针(空表中头结点的指针域为空),因此空表和非空表的处理也就得到了统一。
2.3.2 单链表上基本操作的实现
带头结点单链表的操作代码书写较为方便,如无特殊说明,本节均默认链表带头结点。
1、单链表的初始化
2、求表长操作
3、按序号查找结点
4、按值查找结点
5、插入结点操作
6、删除结点操作
7、采用头插法建立单链表
8、采用尾插法建立单链表
2.3.2.1 带头结点
//单链表--带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* LinkList;
/*
初始化单链表:
1、头指针指向头结点
2、头结点的next初始化为NULL
返回一个LinkList型变量:
具体的值--成功
NULL--失败
*/
LinkList initList(LinkList list){
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return NULL;
}
(*newNode).next=NULL;
list=newNode;
return list;
}
/*
向单链表指定位置插入数据:
LinkList list:单链表
int index:位置
int data: 数据
返回一个int型变量:
1--成功
0--失败
*/
int insertList(LinkList list,int index,int data){
LNode *tmp=list;
int j=0;
if(index<1){
return 0;
}
/*
在index位置插入,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=(*tmp).next;
(*tmp).next=newNode;
return 1;
}
/*
向指定结点后面插入数据
返回一个int型变量:
1--成功
0--失败
*/
int insertNextNode(LNode *p,int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=(*p).next;
(*p).next=newNode;
return 1;
}
/*
向指定结点前面插入数据
第一种方法移动数据
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNodeOne(LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*p).next;
(*p).next=newNode;
(*newNode).data=(*p).data;
(*p).data=data;
return 1;
}
/*
向指定结点前面插入数据
第二种方法循环
LinkList list:单链表
LNode *p:指定结点
int data:数据
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNodeTwo(LinkList list,LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).next!=p){
tmp=(*tmp).next;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=p;
(*tmp).next=newNode;
(*newNode).data=data;
return 1;
}
/*
删除单链表的指定位置的数据
LinkList list:单链表
int index:位置
int *data:被删除的数据
返回一个int型变量:
1--成功
0--失败
*/
int deleteList(LinkList list,int index,int *data){
LNode* tmp=list;
int j=0;
if(index<1){
return 0;
}
/*
删除index位置,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
if((*tmp).next==NULL){
return 0;
}
LNode *p=(*tmp).next;
*data=(*p).data;
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
删除指定结点p
第一种方法移动数据
此方法有bug,如果删除的是最后一个元素,
此方法出错
返回一个int型变量:
1--成功
0--失败
*/
int deleteNodeOne(LNode *p){
if(p==NULL){
return 0;
}
LNode *q=(*p).next;
(*p).next=(*q).next;
(*p).data=(*q).data;
free(q);
return 1;
}
/*
删除指定结点p
第二种方法循环
LinkList list:单链表
LNode *p:指定结点
返回一个int型变量:
1--成功
0--失败
*/
int deleteNodeTwo(LinkList list,LNode *p){
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).next!=p){
tmp=(*tmp).next;
}
if(tmp==NULL){
return 0;
}
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
按位查找:返回指定位置的结点
LinkList list:单链表
int index:位置
返回值:
NULL--失败
具体指针--成功
*/
LNode* getElementByIndex(LinkList list,int index){
LNode *tmp=list;
int j=0;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=(*tmp).next;
j++;
}
return tmp;
}
/*
按值查找:返回指定值的结点
LinkList list:单链表
int data:值
返回值:
NULL--失败
具体指针--成功
*/
LNode* getElementByData(LinkList list,int data){
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).data!=data){
tmp=(*tmp).next;
}
return tmp;
}
/*
求表的长度
*/
int getLength(LinkList list){
int length=0;
LNode *tmp=list;
while((*tmp).next!=NULL){
tmp=(*tmp).next;
length++;
}
return length;
}
/*
新建一个链表:头插法--->相当于逆置链表
链表中有五个元素:5 4 3 2 1
*/
void constructLinkListOne(LinkList list){
int i=0;
for(;i<5;i++){
insertList(list,1,i+1);
}
}
/*
新建一个链表:尾插法
链表中有五个元素:1 2 3 4 5
*/
void constructLinkListTwo(LinkList list){
int i=0;
int j=0;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
LinkList list;
list=initList(list);
constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* LinkList;
LinkList initList(LinkList list){
LNode *newNode=(LNode*)malloc(sizeof(LNode));
if(newNode==NULL){
return NULL;
}
newNode->next=NULL;
list=newNode;
return list;
}
int insertList(LinkList list,int index,int data){
LNode *tmp=list;
int j=0;
if(index<1){
return 0;
}
while((tmp!=NULL)&&(j<index-1)){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
LNode* newNode=(LNode*)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=tmp->next;
tmp->next=newNode;
return 1;
}
int insertNextNode(LNode *p,int data){
if(p==NULL){
return 0;
}
LNode* newNode=(LNode*)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=p->next;
p->next=newNode;
return 1;
}
int insertPriorNodeOne(LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->next=p->next;
p->next=newNode;
newNode->data=p->data;
p->data=data;
return 1;
}
int insertPriorNodeTwo(LinkList list,LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *tmp=list;
if(tmp!=NULL&&tmp->next!=p){
tmp=tmp->next;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->next=p;
tmp->next=newNode;
newNode->data=data;
return 1;
}
int deleteList(LinkList list,int index,int *data){
LNode *tmp=list;
int j=0;
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
if(tmp->next==NULL){
return 0;
}
LNode *p=tmp->next;
*data=p->data;
tmp->next=p->next;
free(p);
return 1;
}
int deleteNodeOne(LNode *p){
if(p==NULL){
return 0;
}
LNode *q=p->next;
p->next=q->next;
p->data=q->data;
free(q);
return 1;
}
int deleteNodeTwo(LinkList list,LNode *p){
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&tmp->next!=p){
tmp=tmp->next;
}
if(tmp==NULL){
return 0;
}
tmp->next=p->next;
free(p);
return 1;
}
LNode* getElementByIndex(LinkList list,int index){
LNode *tmp=list;
int j=0;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=tmp->next;
j++;
}
return tmp;
}
LNode* getElementByData(LinkList list,int data){
LNode *tmp=list;
while(tmp!=NULL&&tmp->data!=data){
tmp=tmp->next;
}
return tmp;
}
int getLength(LinkList list){
int length=0;
LNode *tmp=list;
while(tmp->next!=NULL){
tmp=tmp->next;
length++;
}
return length;
}
void constructLinkListOne(LinkList list){
int i=0;
for(;i<5;i++){
insertList(list,1,i+1);
}
}
void constructLinkListTwo(LinkList list){
int i=0;
int j=0;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
LinkList list;
list=initList(list);
constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
2.3.2.2 不带头结点
//单链表--不带头结点
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* LinkList;
/*
初始化单链表
*/
LinkList initList(LinkList list){
list=NULL;
return list;
}
/*
向单链表第一个位置插入数据
返回一个int型变量:
具体的地址--成功
NULL--失败
*/
LinkList insertFirst(LinkList list,int index,int data){
if(index==1){
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return NULL;
}
(*newNode).next=list;
list=newNode;
(*newNode).data=data;
return list;
}
return NULL;
}
/*
向单链表指定位置插入数据(不包括第一个位置):
LinkList list:单链表
int index:位置
int data: 数据
返回一个int型变量:
1--成功
0--失败
*/
int insertList(LinkList list,int index,int data){
LNode *tmp=list;
int j=1;
if(list==NULL){
return 0;
}
if(index<2){
return 0;
}
/*
在index位置插入,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=(*tmp).next;
(*tmp).next=newNode;
return 1;
}
/*
向指定结点后面插入数据
返回一个int型变量:
1--成功
0--失败
*/
int insertNextNode(LNode *p,int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).next=(*p).next;
(*p).next=newNode;
return 1;
}
/*
向指定结点前面插入数据,此方法不能向第一个结点前面插入数据
(如果此结点是第一个结点,调用insertFirst方法)
第一种方法移动数据
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNodeOne(LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*p).next;
(*p).next=newNode;
(*newNode).data=(*p).data;
(*p).data=data;
return 1;
}
/*
向指定结点前面插入数据,此方法不能向第一个结点前面插入数据
(如果此结点是第一个结点,调用insertFirst方法)
第二种方法循环
LinkList list:单链表
LNode *p:指定结点
int data:数据
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNodeTwo(LinkList list,LNode *p, int data){
if(list==NULL){
return 0;
}
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).next!=p){
tmp=(*tmp).next;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=p;
(*tmp).next=newNode;
(*newNode).data=data;
return 1;
}
/*
删除单链表第一个位置结点
返回一个int型变量:
具体的地址--成功
NULL--失败
*/
LinkList deleteFirst(LinkList list,int index,int *data){
if(index==1){
LNode* tmp=list;
list=(*tmp).next;
*data=(*tmp).data;
free(tmp);
return list;
}
return NULL;
}
/*
删除单链表的指定位置的数据,此方法不能删除第一个位置的结点
(如果删除第一个位置的结点,调用deleteFirst)
LinkList list:单链表
int index:位置
int *data:被删除的数据
返回一个int型变量:
1--成功
0--失败
*/
int deleteList(LinkList list,int index,int *data){
if(list==NULL){
return 0;
}
LNode* tmp=list;
int j=1;
if(index<2){
return 0;
}
/*
删除index位置,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
if((*tmp).next==NULL){
return 0;
}
LNode *p=(*tmp).next;
*data=(*p).data;
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
删除指定结点p,此方法不能删除第一个位置的结点
(如果删除第一个位置的结点,调用deleteFirst)
此方法有bug,如果删除的是最后一个元素,
此方法出错
返回一个int型变量:
1--成功
0--失败
*/
int deleteNodeOne(LNode *p){
if(p==NULL){
return 0;
}
LNode *q=(*p).next;
(*p).next=(*q).next;
(*p).data=(*q).data;
free(q);
return 1;
}
/*
删除指定结点p,此方法不能删除第一个位置的结点
(如果删除第一个位置的结点,调用deleteFirst)
第二种方法循环
LinkList list:单链表
LNode *p:指定结点
返回一个int型变量:
1--成功
0--失败
*/
int deleteNodeTwo(LinkList list,LNode *p){
if(list==NULL){
return 0;
}
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).next!=p){
tmp=(*tmp).next;
}
if(tmp==NULL){
return 0;
}
(*tmp).next=(*p).next;
free(p);
return 1;
}
/*
按位查找:返回指定位置的结点
LinkList list:单链表
int index:位置
返回值:
NULL--失败
具体指针--成功
*/
LNode* getElementByIndex(LinkList list,int index){
LNode *tmp=list;
int j=1;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=(*tmp).next;
j++;
}
return tmp;
}
/*
按值查找:返回指定值的结点
LinkList list:单链表
int data:值
返回值:
NULL--失败
具体指针--成功
*/
LNode* getElementByData(LinkList list,int data){
LNode *tmp=list;
while(tmp!=NULL&&(*tmp).data!=data){
tmp=(*tmp).next;
}
return tmp;
}
/*
求表的长度
*/
int getLength(LinkList list){
if(list==NULL){
return 0;
}
int length=1;
LNode *tmp=list;
while((*tmp).next!=NULL){
tmp=(*tmp).next;
length++;
}
return length;
}
/*
新建一个链表:头插法--->相当于逆置链表
链表中有四个元素:5 4 3 2
*/
LinkList constructLinkListOne(LinkList list){
int i=1;
for(;i<5;i++){
list=insertFirst(list,1,i+1);
}
return list;
}
/*
新建一个链表:尾插法
链表中有四个元素:2 3 4 5
*/
void constructLinkListTwo(LinkList list){
int i=1;
int j=1;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
LinkList list;
list=initList(list);
LNode *newNode=(LNode *)malloc(sizeof(LNode));
(*newNode).next=list;
list=newNode;
(*newNode).data=1;
list=constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct LNode{
int data;
struct LNode *next;
};
typedef struct LNode LNode;
typedef struct LNode* LinkList;
LinkList initList(LinkList list){
list=NULL;
return list;
}
LinkList insertFirst(LinkList list,int index,int data){
if(index=1){
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return NULL;
}
newNode->next=list;
list=newNode;
newNode->data=data;
return list;
}
return NULL;
}
int insertList(LinkList list,int index,int data){
LNode *tmp=list;
int j=1;
if(list==NULL){
return 0;
}
if(index<2){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=tmp->next;
tmp->next=newNode;
return 1;
}
int insertNextNode(LNode *p,int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=p->next;
p->next=newNode;
return 1;
}
int insertPriorNodeOne(LNode *p, int data){
if(p==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->next=p->next;
p->next=newNode;
newNode->data=p->data;
p->data=data;
return 1;
}
int insertPriorNodeTwo(LinkList list,LNode *p, int data){
if(list==NULL){
return 0;
}
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&tmp->next!=p){
tmp=tmp->next;
}
if(tmp==NULL){
return 0;
}
LNode *newNode=(LNode *)malloc(sizeof(LNode));
if(newNode==NULL){
return 0;
}
newNode->next=p;
tmp->next=newNode;
newNode->data=data;
return 1;
}
LinkList deleteFirst(LinkList list,int index,int *data){
if(index==1){
LNode *tmp=list;
list=tmp->next;
*data=tmp->data;
free(tmp);
return list;
}
return NULL;
}
int deleteList(LinkList list,int index,int *data){
if(list==NULL){
return 0;
}
LNode* tmp=list;
int j=1;
if(index<2){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
if(tmp->next==NULL){
return 0;
}
LNode *p=tmp->next;
*data=p->data;
tmp->next=p->next;
free(p);
return 1;
}
int deleteNodeOne(LNode *p){
if(p==NULL){
return 0;
}
LNode *q=p->next;
p->next=q->next;
p->data=q->data;
free(q);
return 1;
}
int deleteNodeTwo(LinkList list,LNode *p){
if(list==NULL){
return 0;
}
if(p==NULL){
return 0;
}
LNode *tmp=list;
while(tmp!=NULL&&tmp->next!=p){
tmp=tmp->next;
}
if(tmp==NULL){
return 0;
}
tmp->next=p->next;
free(p);
return 1;
}
LNode* getElementByIndex(LinkList list,int index){
LNode *tmp=list;
int j=1;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=tmp->next;
j++;
}
return tmp;
}
LNode* getElementByData(LinkList list,int data){
LNode *tmp=list;
while(tmp!=NULL&&tmp->data!=data){
tmp=tmp->next;
}
return tmp;
}
int getLength(LinkList list){
if(list==NULL){
return 0;
}
int length=1;
LNode *tmp=list;
while(tmp->next!=NULL){
tmp=tmp->next;
length++;
}
return length;
}
LinkList constructLinkListOne(LinkList list){
int i=1;
for(;i<5;i++){
list=insertFirst(list,1,i+1);
}
return list;
}
void constructLinkListTwo(LinkList list){
int i=1;
int j=1;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
LinkList list;
list=initList(list);
LNode *newNode=(LNode *)malloc(sizeof(LNode));
(*newNode).next=list;
list=newNode;
(*newNode).data=1;
list=constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
2.3.3 双链表
1、双链表的插入操作
2、双链表的删除操作
3、总结
2.3.3.1 带头结点
//双链表--带头结点
#include <stdio.h>
#include <stdlib.h>
struct DNode{
int data;
struct DNode *prior;
struct DNode *next;
};
typedef struct DNode DNode;
typedef struct DNode* DinkList;
/*
初始化双链表:
1、头指针指向头结点
2、头结点的prior初始化为NULL,永远为NULL
3、头结点的next初始化为NULL
返回一个DinkList型变量:
具体的值--成功
NULL--失败
*/
DinkList initList(DinkList list){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return NULL;
}
(*newNode).prior=NULL;
(*newNode).next=NULL;
list=newNode;
return list;
}
/*
向双链表指定位置插入数据:
DinkList list:双链表
int index:位置
int data: 数据
返回一个int型变量:
1--成功
0--失败
*/
int insertList(DinkList list,int index,int data){
DNode *tmp=list;
int j=0;
if(index<1){
return 0;
}
/*
在index位置插入,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*tmp).next;
if((*tmp).next!=NULL){
(*tmp).next->prior=newNode;
}
(*newNode).prior=tmp;
(*tmp).next=newNode;
(*newNode).data=data;
return 1;
}
/*
向指定结点后面插入数据
返回一个int型变量:
1--成功
0--失败
*/
int insertNextNode(DNode *p,int data){
if(p==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=newNode;
}
(*p).next=newNode;
(*newNode).prior=p;
(*newNode).data=data;
return 1;
}
/*
向指定结点前面插入数据
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNode(DNode *p, int data){
if(p==NULL){
return 0;
}
//找到前一个结点
DNode *tmp=(*p).prior;
if(tmp!=NULL){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).prior=tmp;
(*newNode).next=p;
(*p).prior=newNode;
(*tmp).next=newNode;
return 1;
}
return 0;
}
/*
删除双链表的指定位置的数据
DinkList list:双链表
int index:位置
int *data:被删除的数据
返回一个int型变量:
1--成功
0--失败
*/
int deleteList(DinkList list,int index,int *data){
DNode* tmp=list;
int j=0;
if(index<1){
return 0;
}
/*
删除index位置,需要找到第index-1才可以
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
(*tmp).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=tmp;
}
*data=(*p).data;
free(p);
return 1;
}
/*
删除指定结点p
DinkList list:双链表
DNode *p:指定结点
返回一个int型变量:
1--成功
0--失败
*/
int deleteNode(DNode *p){
if(p==NULL){
return 0;
}
DNode *tmp=(*p).prior;
if(tmp!=NULL){
(*tmp).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=tmp;
}
free(p);
return 1;
}
return 0;
}
/*
按位查找:返回指定位置的结点
DinkList list:双链表
int index:位置
返回值:
NULL--失败
具体指针--成功
*/
DNode* getElementByIndex(DinkList list,int index){
DNode *tmp=list;
int j=0;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=(*tmp).next;
j++;
}
return tmp;
}
/*
按值查找:返回指定值的结点
DinkList list:双链表
int data:值
返回值:
NULL--失败
具体指针--成功
*/
DNode* getElementByData(DinkList list,int data){
DNode *tmp=list;
while(tmp!=NULL&&(*tmp).data!=data){
tmp=(*tmp).next;
}
return tmp;
}
/*
求表的长度
*/
int getLength(DinkList list){
int length=0;
DNode *tmp=list;
while((*tmp).next!=NULL){
tmp=(*tmp).next;
length++;
}
return length;
}
/*
新建一个链表:头插法--->相当于逆置链表
链表中有五个元素:5 4 3 2 1
*/
void constructLinkListOne(DinkList list){
int i=0;
for(;i<5;i++){
insertList(list,1,i+1);
}
}
/*
新建一个链表:尾插法
链表中有五个元素:1 2 3 4 5
*/
void constructLinkListTwo(DinkList list){
int i=0;
int j=0;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
DinkList list;
list=initList(list);
constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct DNode{
int data;
struct DNode *prior;
struct DNode *next;
};
typedef struct DNode DNode;
typedef struct DNode* DinkList;
DinkList initList(DinkList list){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return NULL;
}
newNode->prior=NULL;
newNode->next=NULL;
list=newNode;
return list;
}
int insertList(DinkList list,int index,int data){
DNode *tmp=list;
int j=0;
if(index<1){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->next=tmp->next;
if(tmp->next!=NULL){
tmp->next->prior=newNode;
}
tmp->next=newNode;
newNode->prior=tmp;
newNode->data=data;
return 1;
}
int insertNextNode(DNode *p,int data){
if(p==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->next=p->next;
if(p->next!=NULL){
p->next->prior=newNode;
}
p->next=newNode;
newNode->prior=p;
newNode->data=data;
return 1;
}
int insertPriorNode(DNode *p, int data){
if(p==NULL){
return 0;
}
DNode *tmp=p->prior;
if(tmp!=NULL){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->next=p;
p->prior=newNode;
newNode->prior=tmp;
tmp->next=newNode;
return 1;
}
return 0;
}
int deleteList(DinkList list,int index,int *data){
DNode* tmp=list;
int j=0;
if(index<1){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *p=tmp->next;
if(p==NULL){
return 0;
}
tmp->next=p->next;
if(p->next!=NULL){
p->next->prior=tmp;
}
*data=p->data;
free(p);
return 1;
}
int deleteNode(DNode *p){
if(p==NULL){
return 0;
}
DNode *tmp=p->prior;
if(tmp!=NULL){
tmp->next=p->next;
if(p->next!=NULL){
p->next->prior-tmp;
}
free(p);
return 1;
}
return 0;
}
DNode* getElementByIndex(DinkList list,int index){
DNode *tmp=list;
int j=0;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=tmp->next;
j++;
}
return tmp;
}
DNode* getElementByData(DinkList list,int data){
DNode *tmp=list;
while(tmp!=NULL&&tmp->data!=data){
tmp=tmp->next;
}
return tmp;
}
int getLength(DinkList list){
int length=0;
DNode *tmp=list;
while(tmp->next!=NULL){
tmp=tmp->next;
length++;
}
return length;
}
void constructLinkListOne(DinkList list){
int i=0;
for(;i<5;i++){
insertList(list,1,i+1);
}
}
void constructLinkListTwo(DinkList list){
int i=0;
int j=0;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
DinkList list;
list=initList(list);
constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
2.3.3.1 不带头结点
//双链表--不带头结点
#include <stdio.h>
#include <stdlib.h>
struct DNode{
int data;
struct DNode *prior;
struct DNode *next;
};
typedef struct DNode DNode;
typedef struct DNode* DinkList;
/*
初始化双链表
*/
DinkList initList(DinkList list){
list=NULL;
return list;
}
/*
向双链表第一个位置插入数据
第一个位置的prior指针永远为NULL
返回一个int型变量:
具体的地址--成功
NULL--失败
*/
DinkList insertFirst(DinkList list,int index,int data){
if(index==1){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return NULL;
}
(*newNode).next=list;
(*newNode).prior=NULL;
(*list).prior=newNode;
list=newNode;
(*newNode).data=data;
return list;
}
return NULL;
}
/*
向双链表指定位置插入数据(不包括第一个位置):
DinkList list:双链表
int index:位置
int data: 数据
返回一个int型变量:
1--成功
0--失败
*/
int insertList(DinkList list,int index,int data){
DNode *tmp=list;
int j=1;
if(list==NULL){
return 0;
}
if(index<2){
return 0;
}
/*
在index位置插入,需要找到第index-1才可以
当然,直接循环找到index个结点也可以
因为是双链表
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*tmp).next;
if((*tmp).next!=NULL){
(*tmp).next->prior=newNode;
}
(*newNode).prior=tmp;
(*tmp).next=newNode;
(*newNode).data=data;
return 1;
}
/*
向指定结点后面插入数据
返回一个int型变量:
1--成功
0--失败
*/
int insertNextNode(DNode *p,int data){
if(p==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=newNode;
}
(*p).next=newNode;
(*newNode).prior=p;
(*newNode).data=data;
return 1;
}
/*
向指定结点前面插入数据,此方法不能向第一个结点前面插入数据
(如果此结点是第一个结点,调用insertFirst方法)
返回一个int型变量:
1--成功
0--失败
*/
int insertPriorNode(DNode *p, int data){
if(p==NULL){
return 0;
}
//找到前一个结点
DNode *tmp=(*p).prior;
if(tmp!=NULL){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
(*newNode).data=data;
(*newNode).prior=tmp;
(*newNode).next=p;
(*p).prior=newNode;
(*tmp).next=newNode;
}
return 1;
}
/*
删除双链表第一个位置结点
返回一个int型变量:
具体的地址--成功
NULL--失败
*/
DinkList deleteFirst(DinkList list,int index,int *data){
if(index==1){
DNode* tmp=list;
if(tmp!=NULL){
list=(*tmp).next;
if((*tmp).next!=NULL){
(*tmp).next->prior=NULL;
}
*data=(*tmp).data;
free(tmp);
return list;
}
return NULL;
}
return NULL;
}
/*
删除双链表的指定位置的数据,此方法不能删除第一个位置的结点
(如果删除第一个位置的结点,调用deleteFirst)
DinkList list:双链表
int index:位置
int *data:被删除的数据
返回一个int型变量:
1--成功
0--失败
*/
int deleteList(DinkList list,int index,int *data){
DNode* tmp=list;
if(list==NULL){
return 0;
}
int j=1;
if(index<2){
return 0;
}
/*
删除index位置,需要找到第index-1才可以
当然,直接循环找到index个结点也可以
因为是双链表
*/
while(tmp!=NULL&&j<index-1){
tmp=(*tmp).next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *p=(*tmp).next;
if(p==NULL){
return 0;
}
(*tmp).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=tmp;
}
*data=(*p).data;
free(p);
return 1;
}
/*
删除指定结点p,此方法不能删除第一个位置的结点
(如果删除第一个位置的结点,调用deleteFirst)
返回一个int型变量:
1--成功
0--失败
*/
int deleteNode(DNode *p){
if(p==NULL){
return 0;
}
DNode *tmp=(*p).prior;
if(tmp!=NULL){
(*tmp).next=(*p).next;
if((*p).next!=NULL){
(*p).next->prior=tmp;
}
free(p);
return 1;
}
return 1;
}
/*
按位查找:返回指定位置的结点
DinkList list:双链表
int index:位置
返回值:
NULL--失败
具体指针--成功
*/
DNode* getElementByIndex(DinkList list,int index){
DNode *tmp=list;
int j=1;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=(*tmp).next;
j++;
}
return tmp;
}
/*
按值查找:返回指定值的结点
DinkList list:双链表
int data:值
返回值:
NULL--失败
具体指针--成功
*/
DNode* getElementByData(DinkList list,int data){
DNode *tmp=list;
while(tmp!=NULL&&(*tmp).data!=data){
tmp=(*tmp).next;
}
return tmp;
}
/*
求表的长度
*/
int getLength(DinkList list){
if(list==NULL){
return 0;
}
int length=1;
DNode *tmp=list;
while((*tmp).next!=NULL){
tmp=(*tmp).next;
length++;
}
return length;
}
/*
新建一个链表:头插法--->相当于逆置链表
链表中有四个元素:5 4 3 2
*/
DinkList constructLinkListOne(DinkList list){
int i=1;
for(;i<5;i++){
list=insertFirst(list,1,i+1);
}
return list;
}
/*
新建一个链表:尾插法
链表中有四个元素:2 3 4 5
*/
void constructLinkListTwo(DinkList list){
int i=1;
int j=1;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
DinkList list;
list=initList(list);
DNode *newNode=(DNode *)malloc(sizeof(DNode));
(*newNode).next=list;
list=newNode;
(*newNode).data=1;
list=constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct DNode{
int data;
struct DNode *prior;
struct DNode *next;
};
typedef struct DNode DNode;
typedef struct DNode* DinkList;
DinkList initList(DinkList list){
list=NULL;
return list;
}
DinkList insertFirst(DinkList list,int index,int data){
if(index==1){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return NULL;
}
newNode->next=list;
newNode->prior=NULL;
list->prior=newNode;
list=newNode;
newNode->data=data;
return list;
}
return NULL;
}
int insertList(DinkList list,int index,int data){
DNode *tmp=list;
int j=1;
if(list==NULL){
return 0;
}
if(index<2){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->next=tmp->next;
if(tmp->next!=NULL){
tmp->next->prior=newNode;
}
newNode->prior=tmp;
tmp->next=newNode;
newNode->data=data;
return 1;
}
int insertNextNode(DNode *p,int data){
if(p==NULL){
return 0;
}
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->next=p->next;
if(p->next!=NULL){
p->next->prior=newNode;
}
p->next=newNode;
newNode->prior=p;
newNode->data=data;
return 1;
}
int insertPriorNode(DNode *p, int data){
if(p==NULL){
return 0;
}
DNode *tmp=p->prior;
if(tmp!=NULL){
DNode *newNode=(DNode *)malloc(sizeof(DNode));
if(newNode==NULL){
return 0;
}
newNode->data=data;
newNode->prior=tmp;
newNode->next=p;
p->prior=newNode;
tmp->next=newNode;
}
return 1;
}
DinkList deleteFirst(DinkList list,int index,int *data){
if(index==1){
DNode *tmp=list;
if(tmp!=NULL){
list=tmp->next;
if(tmp->next!=NULL){
tmp->next->prior=NULL;
}
*data=tmp->data;
free(tmp);
return list;
}
return NULL;
}
return NULL;
}
int deleteList(DinkList list,int index,int *data){
DNode* tmp=list;
if(list==NULL){
return 0;
}
int j=1;
if(index<2){
return 0;
}
while(tmp!=NULL&&j<index-1){
tmp=tmp->next;
j++;
}
if(tmp==NULL){
return 0;
}
DNode *p=tmp->next;
if(p==NULL){
return 0;
}
tmp->next=p->next;
if((*p).next!=NULL){
p->next->prior=tmp;
}
*data=p->data;
free(p);
return 1;
}
int deleteNode(DNode *p){
if(p==NULL){
return 0;
}
DNode *tmp=p->prior;
if(tmp!=NULL){
tmp->next=p->next;
if(p->next!=NULL){
p->next->prior=tmp;
}
free(p);
return 1;
}
return 1;
}
DNode* getElementByIndex(DinkList list,int index){
DNode *tmp=list;
int j=1;
if(index<0){
return NULL;
}
while(tmp!=NULL&&j<index){
tmp=tmp->next;
j++;
}
return tmp;
}
DNode* getElementByData(DinkList list,int data){
DNode *tmp=list;
while(tmp!=NULL&&tmp->data!=data){
tmp=tmp->next;
}
return tmp;
}
int getLength(DinkList list){
if(list==NULL){
return 0;
}
int length=1;
DNode *tmp=list;
while(tmp->next!=NULL){
tmp=tmp->next;
length++;
}
return length;
}
DinkList constructLinkListOne(DinkList list){
int i=1;
for(;i<5;i++){
list=insertFirst(list,1,i+1);
}
return list;
}
void constructLinkListTwo(DinkList list){
int i=1;
int j=1;
for(;i<5;i++){
insertList(list,j+1,i+1);
j++;
}
}
int main(){
int length=0;
int i=0;
DinkList list;
list=initList(list);
DNode *newNode=(DNode *)malloc(sizeof(DNode));
(*newNode).next=list;
list=newNode;
(*newNode).data=1;
list=constructLinkListOne(list);
length=getLength(list);
printf("%d",length);
return 0;
}
2.3.4 循环链表
1.循环单链表
2.循环双链表
2.3.5 静态链表
静态链表借助数组来描述线性表的链式存储结构,结点也有数据域data和指针域next,与前面所讲的链表中的指针不同的是,这里的指针是结点的相对地址(数组下标),又称游标。和顺序表一样,静态链表也要预先分配一块连续的内存空间。
2.3.6 顺序表和链表的比较
1.存储(读写)方式
顺序表可以顺序存取,也可以随机存取,链表只能从表头顺序存取元素。例如在第i个位置上执行存或取的操作,顺序表仅需一次访问,而链表则需从表头开始依次访问i次。
2.逻辑结果与物理结构
采用顺序存储时,逻辑上相邻的元素,对应的物理存储位置也相邻。而采用链式存储时,逻辑上相邻的元素,物理存储位置则不一定相邻,对应的逻辑关系是通过指针链接来表示的
3.查找、插入和删除操作
对于按值查找,顺序表无序时,两者的时间复杂度均为O(n);顺序表有序时,可采用折半查找,此时的时间复杂度为O(logn)。
对于按序号查找,顺序表支持随机访问,时间复杂度仅为O(1),而链表的平均时间复杂度为O(n)。顺序表的插入、删除操作,平均需要移动半个表长的元素。链表的插入、删除操作,只需修改相关结点的指针域即可。由于链表的每个结点都带有指针域,故而存储密度不够大。
4.空间分配
顺序存储在静态存储分配情形下,一旦存储空间装满就不能扩充,若再加入新元素,则会出现内存溢出,因此需要预先分配足够大的存储空间。预先分配过大,可能会导致顺序表后部大量闲置;预先分配过小,又会造成溢出。动态存储分配虽然存储空间可以扩充,但需要移动大量元素,导致操作效率降低,而且若内存中没有更大块的连续存储空间,则会导致分配失败。链式存储的结点空间只在需要时申请分配,只要内存有空间就可以分配,操作灵活、高效。
在实际中应该怎样选取存储结构呢?
1.基础存储的考虑
难以估计线性表的长度或存储规模时,不宜采用顺序表;链表不用事先估计存储规模,但链表的存储密度较低显然链式存储结构的存储密度是小于1的。
2.基于运算的考虑
在顺序表中按序号访问a;的时间复杂度为O(1),而链表中按序号访问的时间复杂度为O(n),因此若经常做的运算是按序号访问数据元素,则显然顺序表优于链表。
在顺序表中进行插入、删除操作时,平均移动表中一半的元素,当数据元素的信息量较大且表较长时,这一点是不应忽视的;在链表中进行插入、删除操作时,虽然也要找插入位置,但操作主要是比较操作,从这个角度考虑显然后者优于前者。
3.基于环境的考虑
顺序表容易实现,任何高级语言中都有数组类型;链表的操作是基于指针的,相对来讲,前者实现较为简单,这也是用户考虑的一个因素。
总之,两种存储结构各有长短,选择哪一种由实际问题的主要因素决定。通常较稳定的线性表选择顺序存储,而频繁进行插入、删除操作的线性表(即动态性较强)宜选择链式存储。