线性表链式存储结构通过“链”建立起数据元素之间的逻辑关系,这种用链接方式的线性表简称链表(Link List),在链表上做插入、删除运算不需要移动数据元素。
顺序表和链表的比较
顺序表的优点:
(1)用数组存储数据元素,操作方法简单,容易实现。
(2)不用为表示结点间的逻辑关系而增加额外的存储开销。
(3)存储密度高。
(4)可以随机访问(使用下标访问)。
顺序表的缺点:
(1)做插入,删除操作时,要大量地移动数据元素,效率比较低。
(2)要占用连续的存储空间,且大小要固定,不适合动态存储。
链表的优点:
(1)插入、删除操作简单
(2)大小可变,适合动态存储。
链表的缺点:
(1)查找效率低。
(2)不支持随机存储。
#include<stdio.h>
#include<stdlib.h>
/*
结点定义
*/
typedef int ElemType;
typedef struct node{
ElemType data; //数据域
struct node *next; //指针域
}LNode, *LinkList;
/*
单链表的建立
单链表的建立有两种方法:在链表的头部插入结点和在链表的尾部插入结点(头插法和尾插法)。
*/
//头插法建立单链表
LinkList creat_LinkList1(){
LinkList H = (LinkList)malloc(sizeof(LNode)); //生成头结点。
LNode *s;
H->next = NULL;
int x; //设数据元素的类型为int
scanf("%d", &x);
while(x != -1){
s = (LinkList)malloc(sizeof(LNode));
s->data = x;
s->next = H->next;
H->next = s;
scanf("%d", &x);
}
return H;
}
//尾插法建立单链表
LinkList creat_LinkList2(){
LinkList H = (LinkList)malloc(sizeof(LNode));
H->next = NULL;
LNode *s, *r = H;
int x;
scanf("%d", &x);
while(x != -1){
s = (LinkList)malloc(sizeof(LNode));
s->data = x;
s->next = r->next;
r->next = s;
r = s;
scanf("%d", &x);
}
return H;
}
//求表长
/*
思路:设一个指针p和计数器length,初始化使p指向头结点H,j = 0。若p所指结点还有后继结点,
p向后移动,计数器加1(长度不包括头结点),重复上述过程,直到p->next=NULL为止。
*/
int length_LinkList(LinkList H){
LNode *p = H;
int length = 0;
while(p->next != NULL){
p = p->next;
length++;
}
return length;
}
//查找操作
/*
按序号查找
思路:从链表的第一个元素结点开始判断当前结点是否是dik个,若是,则返回该结点的指针,
否则继续查找下一个,直到表结束为止。没有第k个节点是返回空。
*/
LNode * get_LinkList(LinkList H, int k){
LNode *p = H;
int j = 0;
while(p->next != NULL && j < k){
p = p->next;
j++;
}
if(j == k){
return p;
}else{
return NULL;
}
}
/*
按值查找
思路:从链表的第一个元素结点开始=,判断当前结点的值是否等于x,若是,
返回该结点的指针,否则继续向后查找,直到表结束为止,若查找不到则返回空。
*/
LNode * locate_LinkList(LinkList H, ElemType x) {
LNode * p = H->next;
while(p != NULL && p->data != x){
p = p->next;
}
return p;
}
//单链表的插入
//在单链表H的第i个位置上插入值为x的元素
int insert_LinkList(LinkList H, int i, ElemType x){
LNode *p, *s;
p = get_LinkList(H, i-1);
if(p == NULL){
printf("插入位置i错误");
return -1;
} else{
s = (LinkList)malloc(sizeof(LNode));
s->data = x;
s->next = p->next;
p->next = s;
return 0;
}
}
//删除操作
int del_LinkList(LinkList H, int i){
LinkList p, q;
p = get_LinkList(H, i-1);
if(p == NULL){
printf("第i-1个结点不存在");
return -1;
}else{
if(p->next == NULL){
printf("第i个结点不存在");
return -1;
}else{
q = p->next;
p->next = q->next;
free(q);
return 0;
}
}
}
//单链表的倒置
/*
思路:链表建立时,采用尾插法建立的链表和输入的顺序相反。
*/
void reverse(LinkList H){
LNode *p, *q;
p = H->next;
H->next = NULL;
while(p){
q = p;
p = p->next;
q->next = H->next;
H->next = q;
}
}
void print_LinkList(LinkList H){
LinkList p = H->next;
while(p != NULL){
printf("%d ",p->data);
p = p->next;
}
printf("\n");
}
int main(void){
LinkList H = creat_LinkList2();
print_LinkList(H);
// int length = length_LinkList(H);
// printf("%d\n", length);
// LNode *p = get_LinkList(H, 5);
// if(p != NULL)
// printf("%d", p->data);
// insert_LinkList(H, 4, 4);
// print_LinkList(H);
// del_LinkList(H, 4);
reverse(H);
print_LinkList(H);
return 0;
}
版权声明:本文为xiaoyanol原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。