单向链表定义
对于数组,逻辑关系上相邻的连个元素的物理位置也是相邻的,这种结构的优点是可以随机存储任意位置的元素,但缺点是如果从数组中间删除或插入元素时候,需要大量移动元素,效率不高。
链式存储结构的特点,元素的存储单元可以是连续的,也可以是不连续的,因此为了表示每个元素a,与其接后的元素a+1之间的关系,对于元素a,除了存储其本身信息外,还需要存储一个指示其接后元素的位置。这两部分数据成为结点(node)。
一个结点中存储的数据元素被成为数据域。存储接后存储位置的域叫做指针域。n个结点(ai(1<=i<=n)的存储映像链接成一个链表。
整个链表必须从头结点开始进行,头结点的指针指向下一个结点的位置,最后一个结点的指针指向NULL。
在链表中,通过指向接后结点位置的指针实现将链表中每个结点“链”到一起。链表中第一个结点称之为头结点。
单向链表数据结构定义
struct list
{
int data;//链表数据域
struct list *next;//链表指针域
};
单向链表的实现
struct list *create_list()//建立一个节点
void traverse(struct list *ls)//循环遍历链表
struct list *insert_list(struct list *ls, int n, int data)//在指定位置插入元素
int delete_list(struct list *ls, int n)//删除指定位置元素
int count_list(struct list *ls)//返回链表元素个数
void clear_list(struct list *ls)//清空链表,只保留首节点
int empty_list(struct list *ls)//返回链表是否为空
struct list *locale_list(struct list *ls, int n)//返回链表指定位置的节点
struct list *elem_locale(struct list *ls, int data)//返回数据域等于data的节点
int elem_pos(struct list *ls, int data)//返回数据域等于data的节点位置
struct list *last_list(struct list *ls)//得到链表最后一个节点
void merge_list(struct list *st1, struct list *ls2)//合并两个链表,结果放入st1中
void reverse(struct list *ls)//链表逆置
删除元素操作
逆置链表-方式1,移动指针域
逆置链表-方式2,移动数据域
逆置操作
1.判断首节点的next是否为NULL;
2.判断首节点next的next是否为空,如果为空证明链表除首节点之外只有一个节点,所以不需要逆置;
3.定义一个指针last,指向首节点的next域,因为逆置之后,该域为链表尾节点;
4.定义三个指针,分别代表前一个节点,当前节点,下一个节点;
5.前节点指向链表首节点;
6.当前节点指向链表首节点的next域;
7.下一个节点为NULL;
8.循环条件判断当前节点是否为NULL,如果为NULL退出循环;
a)下一个节点指向当前节点的下一个节点;
b)当前节点的下一个节点指向前一个节点;
c)前一个节点指向当前节点;
d)当前节点指向下一个节点;
9.循环完成;
10.设置last节点的next为NULL;
11.设置链表首节点的next为前一个节点。
代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
struct list {
int data;
struct list *next;
};
/**
* 创建节点.
* @return
*/
struct list *create_list() {
struct list *p = malloc(sizeof(struct list));
memset(p, 0, sizeof(p));
return p;
}
/**
* 指定位置插入节点.
* @param ls
* @param n
* @param data
* @return
*/
struct list *insert_list(struct list *ls, int n, int data) {
struct list *p = ls;
while (p && n--) {
p = p->next;
}
if (p == NULL)
return NULL;
struct list *node = create_list();
memset(node, 0, sizeof(node));
node->data = data;
node->next = p->next;
p->next = node;
return node;
}
/**
* 删除指定节点
* @param ls
* @param n
* @return
*/
int delete_list(struct list *ls, int n) {
struct list *p = ls;
while (p && n--) {
p = p->next;
}
struct list *q = p->next;
int data = q->data;
p->next = q->next;
free(q);
return data;
}
/**
* 计算列表长度.
* @param ls
* @return
*/
int count_list(struct list *ls) {
// 不能算首节点.
struct list *p = ls->next;
int count = 0;
while (p) {
p = p->next;
count++;
}
return count;
}
void clear_list(struct list *ls) {
// 清空节点,但是不能释放头节点.
struct list *p = ls->next;
while (p) {
struct list *q = p->next;
free(p);
p = q;
}
// 重点,这里必须把首节点的next置空.
ls->next = NULL;
}
/**
* 寻找最后一个节点
* @param ls
* @return
*/
struct list *last_list(struct list *ls) {
struct list *p = ls;
struct list *last = NULL;
while (p) {
last = p;
p = p->next;
}
return last;
}
/**
* 合并列表
* @param st1
* @param ls2
*/
void merge_list(struct list *st1, struct list *ls2) {
struct list *last = last_list(st1);
last->next = ls2->next;
free(ls2);
}
/**
* 列表翻转.
* @param ls
*/
void reverse(struct list *ls) {
struct list *pre = ls;
struct list *cur = ls->next;
struct list *next = NULL;
struct list *last = ls->next;
while (cur) {
next = cur->next;
cur->next = pre;
pre = cur;
cur = next;
}
last->next = NULL;
ls->next = pre;
}
// 链表的冒泡排序
void bubble_sort(struct list *ls) {
int count = count_list(ls);
int i,j;
for (i = 0; i< count; i++) {
struct list *p = ls->next;
for (j = 0; j < count - i - 1; j++) {
struct list *q = p->next;
if (p->data > q->data) {
int temp = q->data;
q->data = p->data;
p->data = temp;
}
p = q;
}
}
}
/**
* 遍历列表
* @param ls
*/
void traverse(struct list *ls) {
struct list *p = ls->next;
while (p) {
printf("data = %d\n", p->data);
p = p->next;
}
}
int main() {
int i;
struct list *first = create_list();
struct list *second = create_list();
for (i = 0; i < 10; i++) {
struct list *node = create_list();
insert_list(first, i, i);
}
for (i = 100; i < 110; i++) {
struct list *node = create_list();
insert_list(second, 0, i);
}
//clear_list(first);
printf("count = %d\n", count_list(first));
delete_list(first, 3);
//traverse(first);
printf("data = %d\n", last_list(first)->data);
printf("Hello, World!\n");
merge_list(first, second);
//traverse(first);
printf("-----------------\n");
reverse(first);
traverse(first);
printf("-----------------\n");
printf("-----------------\n");
bubble_sort(first);
traverse(first);
return 0;
}