用C语言编写链式存储结构下实现线性表的创建,插入,删除,按值查找
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用C语言编写链式存储结构下实现线性表的创建,插入,删除,按值查找相关的知识,希望对你有一定的参考价值。
参考技术A #include <stdio.h>#include <stdlib.h>
typedef struct LNode
int data; //链表数据
struct LNode* next; //链表指针
LNode,*LinkList;
/*头插法-建立单链表*/
LinkList HeadCreate(LinkList la)
int num;
la=(LinkList)malloc(sizeof(LNode)); //建立头结点
la->next=NULL;
scanf("%d",&num);
while(num!=10)
LNode *p=(LinkList)malloc(sizeof(LNode));
p->data=num;
p->next=la->next;
la->next=p;
scanf("%d",&num);
return la;
/*尾插法-建立单链表*/
LinkList TailCreate(LinkList la)
int num;
la=(LinkList)malloc(sizeof(LNode));
la->next=NULL;
LinkList s,r=la;
scanf("%d",&num);
while(num!=10)
s=(LinkList)malloc(sizeof(LNode));
s->data=num;
r->next=s;
r=s;
scanf("%d",num);
r->next=NULL;
return la;
/*单链表遍历*/
void TravelList(LinkList la)
LinkList p=la->next;
while(p!=NULL)
printf("%d->",p->data);
p=p->next;
printf("\n");
/*单链表的按位查找*/
LinkList GetElem(LinkList la,int i)
int j=1;
LNode* p=la->next;
if(i<1)
return NULL;
while(p && j<i)
p=p->next;
j++;
return p;
/*单链表的按值查找*/
LinkList LocalElem(LinkList la,int e)
LNode* p=la->next;
while(p!=NULL && p->data!=e)
p=p->next;
return p;
/*单链表插入操作*/
bool InsertList(LinkList la,int i,int e)
//在la链表中的i位置插入数值e
int j=1;
LinkList p=la,s;
while(p && j<i)
p=p->next;
j++;
if(p==NULL)
return false;
if((s=(LinkList)malloc(sizeof(LNode)))==NULL)
return false;
s->data=e;
s->next=p->next;
p->next=s;
return true;
/*单链表删除操作*/
bool DeleteList(LinkList la,int i)
int j=1;
LinkList p=la,q;
while(p && j<i) //p指向第i-1个元素
p=p->next;
j++;
if(p==NULL || p->next==NULL) //表示不存在第i-1个和第i的元素
return false;
q=p->next;
p->next=q->next;
free(q);
return true;
/*单链表的表长*/
int LengthList(LinkList la)
int nLen=0;
LinkList p=la->next;
while(p)
p=p->next;
nLen++;
return nLen;
/*单链表逆置*/
LinkList Reserve(LinkList la)
if(la==NULL || la->next==NULL)
return la;
LinkList p=la->next,q=p->next,r=q->next;
la->next=NULL;
p->next=NULL;
while(r!=NULL)
q->next=p;
p=q;
q=r;
r=r->next;
q->next=p;
la->next=q;
return la;
int main()
LNode la;
LinkList p;
p=HeadCreate(&la); //头插法创建单链表
TravelList(p);
printf("%p\n",GetElem(p,1)); //获得第1个结点地址
InsertList(p,2,10); //在链表的第2个位置插入元素10
TravelList(p);
DeleteList(p,3); //删除链表的第3个元素
TravelList(p);
printf("%d\n",LengthList(p)); //获得链表长度
p=Reserve(p);
TravelList(p);
return 0;
//运行结果
//5 6 12 7 8 14 9 3 2 5 14 10 头插法创建链表
//14->5->2->3->9->14->8->7->12->6->5-> 显示链表
//00382490 第一个结点的地址
//14->10->5->2->3->9->14->8->7->12->6->5-> 插入元素值为10的结点
//14->10->2->3->9->14->8->7->12->6->5-> 删除第三个结点
//11 获得链表长度
//5->6->12->7->8->14->9->3->2->10->14-> 链表逆置
//Press any key to continue
这是我写的一个线性表链式存储的综合程序,包含了你所要的创建、删除、插入、按值查找的功能,还有一些额外的功能。下面加注释的是程序运行结果,你可以参考试着改改程序,让程序更加完美。希望对你有帮助,呵呵!本回答被提问者采纳
线性表的链式存储(C代码实现)
线性表的链式存储结构
线性表的实现分顺序存储结构和链式存储结构。
上一节我们学学习了线性表的实现分顺序存储结构,并实现解顺序存储的基本操作。
这一节我们来学习线性表链式存储结构,那我们再想象一下我为什么我们要引入链式存储结构,万物存在必有其道理
主要还是因为线性存储结构存在着这样一个问题:当我们需要插入和删除元素时,就必须挪动大量与之无关的元素,因为线性存储结构结点与节点之间的关系是相邻关系,一个节点挨着一个节点
如为了插入或者删除一个元素移动大量的元素,这样就降低了程序运行效率。
当我们引入
顾名思义链式存储结构,数据与数据之间是以链式关系来产生连接的的,我们可以脑部一下锁链的样子,不扯淡了,进入正题--
我们如何定义一个链式存储结构的节点呢?
/*Node表示一个节点*/
typedef struct Node{
int data; //数据域
struct Node* next; //存放下一个节点的指针
}Node;
typedef struct Node* LinkList; /*取了一个别名,定义LinkList = Node*,用于存放节点的指针*/
一个节点包括一个数据域和指针域
我们将这种只带有一个指针域的线性表称为单链表。
链表中第一个结点的存储位置叫做头指针。
单链表的第一个结点前附设一个结点,称为头结点。
注意可以没有头节点,但是要是链表,就一定存在头指针。
那么问题来了,我们如何区分头节点和头指针呢?
头指针:是指向链表的指针,如果不存在头节点,那么头指针就会指向链表的第一个节点。
头节点:实际上是不存在的,只不过是为了链表的一些操作方便而设置的,头节点与第一个节点以链式关系相连,并且头节点的数据域没有意义,指针域存放第一个节点的地址。
单链表的插入
s->next =p->next;
p->next=s; //注意前后顺序不能调
单链表的删除
q= p->next;
p->next = q->next;
free(q);
单链表的建表(头插法)
顾名思义直接插在第一位,就是头节点的后面。
1 void CreateListHead(LinkList *L,int n){
2
3 LinkList p;
4 *L = (Node*)malloc(sizeof(Node)); //生成的新节点节点要初始化
5 (*L)->next=NULL; //并指向空
6
7 for(int i=0;i<n;i++){
8 p =(Node*)malloc(sizeof(Node)); //新生成的节点节点要初始化
9 p->data=i;
10 p->next=(*L)->next; //这里不能指向NULL
11 (*L)->next =p; //两级指针
12 }
13 }
单链表的建表(尾插法)
1 void CreateListTail(LinkList *L ,int n){
2
3 LinkList p,r; //生成节点p,存放Node地址
4 *L = (Node*)malloc(sizeof(Node)); //生成的头节点节点要初始化
5 (*L)->next=NULL;
6 r = *L; //用于遍历
7
8 for(int i=0;i<n;i++){
9 p =(Node*)malloc(sizeof(Node)); //新生成的节点节点要初始化
10 p->data=i;
11 r->next=p;
12 r=p; //r指针移动到p上r ,以便
13 }
14 r->next=NULL; //最后一个指向空
15 }
单链表的遍历
1 void TraverseList(LinkList L){
2 LinkList p;
3 p = L->next;
4 while(p){
5 printf("%d ",p->data);
6 p=p->next;
7 }
8 }
清空单链表
1 /*清空链表*/
2 void ClearList(LinkList L){
3 LinkList p ,q;
4 p = L->next; //指向第一个元素
5 while(p){
6 q=p->next; //q指向了p的下一个
7 free(p); //释放内存
8 p =q;
9 }
10 L->next =NULL; //头节点指向空
11 }
其它的一下操作见下面代码吧
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include "time.h" 4 5 /*Node表示一个节点*/ 6 typedef struct Node{ 7 int data; 8 struct Node* next; 9 }Node; 10 typedef struct Node* LinkList; /*定义LinkList*/ 11 12 /*初始化链表*/ 13 int InitList(LinkList *L){ 14 *L=(LinkList)malloc(sizeof(Node)); //这里的*L就是Node节点的指针对象 15 if(!(*L)) //申请内存失败 16 return 0; 17 (*L)->next=NULL; 18 return 1; 19 } 20 21 //头插法,n表示插入的个数 22 void CreateListHead(LinkList *L,int n){ 23 24 LinkList p; 25 *L = (Node*)malloc(sizeof(Node)); //生成的新节点节点要初始化 26 (*L)->next=NULL; //并指向空 27 28 for(int i=0;i<n;i++){ 29 p =(Node*)malloc(sizeof(Node)); //新生成的节点节点要初始化 30 p->data=i; 31 p->next=(*L)->next; //这里不能指向NULL 32 (*L)->next =p; //两级指针 33 } 34 } 35 //尾插法,n表示插入的个数 36 void CreateListTail(LinkList *L ,int n){ 37 38 LinkList p,r; //生成节点p,存放Node地址 39 *L = (Node*)malloc(sizeof(Node)); //生成的头节点节点要初始化 40 (*L)->next=NULL; 41 r = *L; //用于遍历 42 43 for(int i=0;i<n;i++){ 44 p =(Node*)malloc(sizeof(Node)); //新生成的节点节点要初始化 45 p->data=i; 46 r->next=p; 47 r=p; //r指针移动到p上r ,以便 48 } 49 r->next=NULL; //最后一个指向空 50 } 51 52 /*遍历链表*/ 53 void TraverseList(LinkList L){ 54 LinkList p; 55 p = L->next; 56 while(p){ 57 printf("%d ",p->data); 58 p=p->next; 59 } 60 } 61 62 /*清空链表*/ 63 void ClearList(LinkList L){ 64 LinkList p ,q; 65 p = L->next; //指向第一个元素 66 while(p){ 67 q=p->next; //q指向了p的下一个 68 free(p); //释放内存 69 p =q; 70 } 71 L->next =NULL; //头节点指向空 72 } 73 74 /*获取链表长度*/ 75 int GetLengthList(LinkList L){ 76 LinkList p; 77 p=L->next; 78 int count=0; //计数器 79 while(p){ 80 count++; 81 p= p ->next; 82 } 83 return count; 84 85 } 86 87 /*删除元素*/ 88 void DeleteElem(LinkList L,int n){ 89 int count=0; 90 LinkList p ,q; 91 p =L; //注意这里的p不在指向第一个节点了 92 count =1; 93 while(p->next && count<n){ // 94 p =p->next; 95 ++count; 96 } 97 if(!(p->next) || count>n) 98 printf("没有找到可删除的元素"); 99 q= p->next; 100 p->next = q->next; 101 free(q); 102 } 103 104 /*插入元素 n是位置,c是数*/ 105 void InsertElemList(LinkList L,int n,int c){ 106 107 int count=0; 108 LinkList p,s; 109 p =L; //注意这里的p不在指向第一个节点了 110 count =1; 111 while(p->next && count<n){ // 112 p =p->next; 113 ++count; 114 } 115 s =(Node*)malloc(sizeof(Node)); 116 s->data=c; 117 s->next =p->next; 118 p->next=s; 119 120 } 121 122 /* 初始条件:顺序线性表L已存在 */ 123 /* 操作结果:返回L中第1个与e满足关系的数据元素的位序。 */ 124 /* 若这样的数据元素不存在,则返回值为0 */ 125 int LocateElem(LinkList L,int e){ 126 127 LinkList p; 128 p =L->next; 129 while(p){ 130 if(p->data == e) 131 return 1; 132 p =p->next; 133 } 134 return 0; 135 } 136 137 /*获取元素,n表示第几个,并返回查到的值*/ 138 int GetElem(LinkList L,int n){ 139 140 LinkList p; //生成节点p,存放Node地址 141 p = L->next; //p指向第一个元素 142 int count=1; //计数器 143 144 while(p && count<n){ //查找 145 p = p->next; 146 count++; 147 } 148 if(!p || count>n){ //没找到 149 return 0; 150 } 151 int ret = p->data; //找到 152 return ret; 153 } 154 155 /*判断链表是否为空*/ 156 int ListElmpty(LinkList L){ 157 158 if(L->next){ 159 return 0; 160 }else{ 161 return 1; 162 } 163 } 164 165 int main(){ 166 LinkList L1; //创建一个节点,用于头插法 167 LinkList L2; //创建一个节点,用于尾插法 168 169 printf("......头插法...... "); 170 InitList(&L1); //初始化 171 CreateListHead(&L1,5); 172 TraverseList(L1); 173 printf(" "); 174 175 printf("......尾插法...... "); 176 InitList(&L2); //初始化 177 CreateListTail(&L2,5); 178 TraverseList(L2); 179 printf(" "); 180 181 //获取元素的值 182 int getElem= GetElem(L2,3); 183 printf("%d ",getElem); 184 185 //获取长度 186 int GetLength=GetLengthList(L2); 187 printf("L1链表的长度:%d",GetLength); 188 printf(" "); 189 190 //删除L1中2号元素 191 printf("删除L1中2号元素:"); 192 DeleteElem(L1,2); 193 TraverseList(L1); 194 printf(" "); 195 196 //在第三个位置插入11 197 printf("在第三个位置插入11元素:"); 198 InsertElemList(L1,3,11); 199 TraverseList(L1); 200 printf(" "); 201 202 int localFind=LocateElem(L1,11); 203 printf("找到了吗: %d d",localFind); 204 205 //判断L1是否为空 206 int lstElempty=ListElmpty(L1); 207 printf("L1为空吗: %d ",lstElempty); 208 //清空L1 209 ClearList(L1); 210 //在判断L1是否为空 211 lstElempty=ListElmpty(L1); 212 printf("L1为空吗: %d ",lstElempty); 213 214 return 0; 215 }
写完插入和删除操作,我们便可以看出,链式存储结构对于插入和删除的优势是明显的,不需要进行大量的元素的移动。
当然单链表这么个优秀,也是存在缺点的
缺点就是其不便于进行查找和修改,每查找或者修改一个元素就要开始从头开始遍历 - -这么坑爹的吗 ?没错 就是这么坑爹 - -
所以当我们应用的场合不同 ,就用不同的存储结构。
以上是关于用C语言编写链式存储结构下实现线性表的创建,插入,删除,按值查找的主要内容,如果未能解决你的问题,请参考以下文章
用C语言建立一个顺序存储的线性表并实现线性表的插入和删除操作
数据结构实验:线性表的顺序表示和链式表示及插入、删除、查找运算