单向链表的基本实现

一、基本概念

链表:是一种线性表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer)。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而顺序表相应的时间复杂度分别是O(logn)和O(1)。(来自wikipedia);

链表和数组的区别:

1.数组申请的是一块连续的内存空间,并且在编译阶段就确定了空间大小,运行阶段是不允许改变的,不能适应数据动态地增减。当数据增加时会造成数据越界;当数据减少时会造成内存浪费。但是数组是从栈中分配空间,对于程序员方便快速,并且数组可以根据下标直接存储数据。在增加元素时需要移动大量元素。因此数组便于快速访问数据,但是对于元素的插入和删除会有很多繁琐的操作。

2.链表动态地进行存储分配,现用现申请,可以适应数据动态的增减,并且可以方便的插入、删除数据。链表从堆中获取内存,并且是物理上非连续的内存空间,能够有效的避免一些内存碎片问题。并且可以利用链表来利用一些碎片化的地址空间。

二、单链表

单向链表(单链表)是链表的一种,其特点是链表的链接方向是单向的,对链表的访问要通过从头部开始,依序往下读取。


三、链表的实现

1.链表由各个节点组成,由上图可知,链表节点中包含:数据位、指针;数据位用来保存节点数据信息,指针用来指向下一个节点。则用C语言实现节点为:

typedef struct List{

List* next;

int data;

}list;

2.链表的头

链表头只用来表明链表的入口地址;实现为:

list* head=(list*)malloc(sizeof(list));

head->next=NULL;

3.在链表中添加节点

a.头插法:

//在头节点后添加链表节点
void add_node_head(list* head, int data) {
list *p= (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error/n"); return; }
list* q = head->next;
head->next = p;
p->next = q;
p->data = data;

}

b.在尾部插入数据

//在链表的尾部添加节点

void add_node_last(list* head,int data) {
list *p = (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error\n"); return; }

list* q = head;
while (q->next != NULL) {
q = q->next;
}
q->next = p;
p->next = NULL;
p->data = data;

}

c.在任意位置插入数据

//在第i个节点处添加新节点
void add_i_node(list* head,int i,int data) {
list *p = (list*)malloc(sizeof(list));
if (p == NULL) { printf("add error\n"); return; }
if (i <= 0) { printf("add i error\n"); return; }
if (i > num_node(head)) { add_node_last(head, data); return; }//如果要插入的节点大于总节点数则插入在最后
//先找到第i-1个节点处
list* q = head;
int num = 0;
while (1) {
if (num == i - 1) { break; }
q = q->next;
num++;
}
//先保存原先的第i个节点
list* node_i = q->next;

q->next = p;
p->next = node_i;
p->data = data;

}

4.删除节点

void del_i_node(list* head,int i) {
if (i > num_node(head)) { printf("del i error\n"); return; }
if (i < 1 ) { printf("del i error\n"); return; }

//先找到第i-1个节点处
list* q = head;
int num = 0;
while (1) {
if (num == i - 1) { break; }
q = q->next;
num++;
}

//先保存原先的第i个节点
list* node_i = q->next;

q->next = q->next->next;
free(node_i);//手动释放申请的内存空间

}

5.链表的遍历

//遍历整个链表
void list_see(list* head) {
list* q = head;
int num = 0;
while (q->next != NULL) {
q = q->next;
num++;
printf("node_%d = %d.\n",num,q->data);
}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章