单链表:
特点: 链表的链接方向是单向的;
链表是由节点构成,每个节点由两部分(节点数据和指向下一节点的指针);
>
链表的结构体及变量重定义如下:
#ifndef LIST_H_
#define LIST_H_
#define ONE 1
#define ZERO 0
#define TWO 2
//const int TRUE = 1;
//const int FALSE = 0;
enum BOOL {
FALSE,
TRUE
};
typedef unsigned char Boolean;
//定义连表的控制节点
typedef struct List{
struct List_node *head;
struct List_node *tail;
int count;
}List;
typedef struct List_node{
int data;
struct List_node *next;
}List_node;
>
链表的常用接口如下:
List *init_list(void) ; //链表的初始化
void destroy_list(List **list) ; //连表的销毁
Boolean push_front(List *list, int value) ; //头部插入
Boolean push_back(List *list, int value) ; //尾部插入
Boolean pop_front(List *list) ; //头部删除
Boolean pop_back(List *list) ; //尾部删除
void print_list(List *list) ; //打印链表
void sort_list_ascend(List *list) ; //升序排列连表
void sort_list_descend(List *list) ; //降序
int get_list_count(List *list) ; //得到连表节点个数
List *merge_two_lists(List *list1, List *list2) ; //合并两个连表
List_node *find_revise_node(List *list, int num) ; //找到连表倒数第num个节点
List_node *find_middle_node(List *list) ; //得到链表的中间节点
List *reverse_list(List *list) ; //逆置链表
List *copy_list(List *list) ; //链表的拷贝
Boolean is_list_intersect(List *list1, List *list2) ; //判断两个链表是否有交点
List_node *find_first_common_node(List *list1, List *list2); //找到两个链表的第一个交点
void delete_one_node(List *list, List_node *node) ; //删除链表的一个节点
Boolean has_circle(List *list) ; //判断链表是否有环
List_node *find_circle_begin(List *list) ; //找到链表环的入口
链表的接口实现
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include "list.h" //""当前目录查找头文件 <>在标准库中找
static void *Malloc(size_t size);
static List_node *create_node(void);
static List_node *create_node(void)
{
List_node *node = NULL;
node = (List_node *)Malloc(sizeof(List_node));
bzero(node, sizeof(List_node));
return node;
}
static void *Malloc(size_t size)
{
void *result = malloc(size);
if(result == NULL){
fprintf(stderr, "the mmemory is full!\n");
exit(1);
}
return result;
}
List *init_list(void) //链表的初始化
{
List *list = NULL;
list = (List *)Malloc(sizeof(List));
bzero(list, sizeof(List)); //对申请的内存进行初始化(清空)
return list;
}
void destroy_list(List **list) //连表的销毁
{
//销毁步骤:(1)销毁链表节点
// (2)销毁控制信息
// (3)指针置为空
if(list == NULL || *list == NULL){
return ;
}
while((*list)->count){
pop_front(*list);
}
free(*list);
*list = NULL;
}
Boolean push_front(List *list, int value) //头部插入
{
List_node *node = NULL;
if(list == NULL){
return FALSE;
}
node = create_node();
node->data = value;
//两种情况:1.链表数目为空
if(list->count){
node->next = list->head;
list->head = node;
}else{ //2.node既是head也是tail
list->head = list->tail = node;
}
list->count++;
return TRUE;
}
Boolean push_back(List *list, int value) //尾部插入
{
List_node *node = NULL;
if(list == NULL){
return FALSE;
}
node = create_node();
node->data = value;
if(list->count){
list->tail->next = node;
list->tail = node;
}else{
list->head = list->tail = node;
}
list->count++;
return TRUE;
}
Boolean pop_front(List *list) //头部删除
{
List_node *p_node = NULL;
if(list == NULL || list->count == ZERO){
return FALSE;
}
p_node = list->head;
if(list->count == ONE){
list->head = list->tail = NULL;
}else{
list->head = p_node->next;
}
free(p_node);
p_node = NULL;
list->count--;
return TRUE;
}
Boolean pop_back(List *list) //尾部删除
{
List_node *p_node = NULL;
if(list == NULL || list->count == ZERO){
return FALSE;
}
p_node = list->head;
if(list->count == ONE){
list->head = list->tail = NULL;
free(p_node);
}else{
while(p_node->next != list->tail){
p_node = p_node->next;
}
free(list->tail);
list->tail = p_node;
p_node = NULL;
}
list->count--;
return TRUE;
}
void print_list(List *list) //打印链表
{
List_node *p_node = NULL;
if(list == NULL || list->count <= ZERO){
return ;
}
p_node = list->head;
while(p_node != NULL){
printf("%d ", p_node->data);
p_node = p_node->next;
}
printf("\n");
}
static void swap(void *a, void *b, int length);
static void swap(void *a, void *b, int length)
{
void *temp = Malloc(length);
memcpy(temp, a, length);
memcpy(a, b, length);
memcpy(b, temp, length);
free(temp);
}
void sort_list_ascend(List *list) //升序排列连表
{
List_node *p_node = NULL;
List_node *q_node = NULL;
if(list == NULL || list->count < 2){
return ;
}
for(p_node = list->head; p_node->next; p_node = p_node->next){
for(q_node = p_node->next; q_node; q_node = q_node->next){
if(p_node->data > q_node->data){
swap(&p_node->data, &q_node->data, sizeof(int));
}
}
}
}
void sort_list_descend(List *list) //降序
{
List_node *p_node = NULL;
List_node *q_node = NULL;
if(list == NULL || list->count < 2){
return ;
}
for(p_node = list->head; p_node->next; p_node = p_node->next){
for(q_node = p_node->next; q_node; q_node = q_node->next){
if(p_node->data < q_node->data){
swap(&p_node->data, &q_node->data, sizeof(int));
}
}
}
}
int get_list_count(List *list) //得到连表节点个数
{
if(list = NULL){
return -1;
}
return list->count;
}
List *merge_two_lists(List *list1, List *list2) //合并两个连表
{
List *list3 = NULL;
List_node *p_node = NULL;
List_node *q_node = NULL;
if(list1 == NULL && list2 == NULL){
return list3;
}
list3 = init_list();
p_node = list1->head;
q_node = list2->head;
while(p_node != NULL && q_node != NULL){
if(p_node->data <= q_node->data){
push_back(list3, p_node->data);
p_node = p_node->next;
}else{
push_back(list3, q_node->data);
q_node = q_node->next;
}
}
while(p_node != NULL){
push_back(list3, p_node->data);
p_node = p_node->next;
}
while(q_node != NULL){
push_back(list3, q_node->data);
q_node = q_node->next;
}
return list3;
}
List_node *find_revise_node(List *list, int num) //找到连表倒数第num个节点
{
//若不知list->count,可以使用快慢指针来解决--->先让一个指针向后移动num-1步,
//后 让另外一个指针和该指针一起向后移动,当该指针移动到末尾时即慢指针所在位
//置即为所找节点
#if 0
List_node *p_node = NULL;
int count = 0;
if(list == NULL || num <= ZERO || list->count == ZERO
|| num > list->count){
return NULL;
}
p_node = list->head;
count = list->count - num;
while(count--){
p_node = p_node->next;
}
return p_node;
#endif
#if 1
List_node *p_node = NULL;
List_node *q_node = NULL;
int count = 0;
if(list == NULL || num <= ZERO){
return NULL;
}
p_node = list->head;
q_node = list->head;
count = num - 1;
while(count--){
p_node = p_node->next;
}
while(p_node->next != NULL){
p_node = p_node->next;
q_node = q_node->next;
}
return q_node;
#endif
}
List_node *find_middle_node(List *list) //得到链表的中间节点
{
List_node *mid_node = NULL;
int count = 0;
if(list == NULL){
return mid_node;
}
mid_node = list->head;
count = list->count >> 1;
while(count--){
mid_node = mid_node->next;
}
return mid_node;
}
List *reverse_list(List *list) //逆置链表
{
#if 0
List *new_list = NULL;
List_node *p_node = NULL;
// List_node *q_node = NULL;
if(list == NULL || list->count <= ONE){
return new_list;
}
p_node = list->head;
new_list = init_list();
//q_node = new_list->head;
while(p_node != NULL){
push_front(new_list, p_node->data);
p_node = p_node->next;
}
return new_list;
#endif
#if 1
List_node *p_node = NULL;
List_node *q_node = NULL;
List_node *r_node = NULL;
if(list == NULL || list->count <= ONE){
return list;
}
if(list->count == TWO){
list->tail->next = list->head;
list->head->next = NULL;
}else{
p_node = list->head;
q_node = p_node->next;
r_node = q_node->next;
p_node->next = NULL;
do{
q_node->next = p_node;
p_node = q_node;
q_node = r_node;
r_node = r_node->next;
}while(r_node != NULL);
q_node->next = p_node;
}
swap(&list->head, &list->tail, sizeof(List_node *));
return list;
#endif
}
List *copy_list(List *list) //链表的拷贝
{
List *result = NULL;
List_node *p_node = NULL;
if(list == NULL){
return NULL;
}
result = init_list();
p_node = list->head;
while(p_node != NULL){
push_back(result, p_node->data);
p_node = p_node->next;
}
return result;
}
Boolean is_list_intersect(List *list1, List *list2) //判断两个链表是否有交点
{
if(list1 == NULL || list2 == NULL || list1->count == ZERO
|| list2->count == ZERO){
return FALSE;
}
return list1->tail == list2->tail;
#if 0
if(list1->tail == list2->tail){
return TRUE;
}else{
return FALSE;
}
#endif
}
List_node *find_first_common_node(List *list1, List *list2) //找到两个链表的第一个交点
{
int len = 0;
int l1_len = 0;
int l2_len = 0;
List_node *p_node = NULL;
List_node *q_node = NULL;
if(list1 == NULL || list2 == NULL || list1->count == ZERO
|| list2->count == ZERO || is_list_intersect == FALSE){
return NULL;
}
l1_len = list1->count;
l2_len = list2->count;
p_node = list1->head;
q_node = list2->head;
if(l1_len >= l2_len){
len = l1_len - l2_len;
while(len--){
p_node = p_node->next;
}
}else{
len = l2_len - l1_len;
while(len--){
q_node = q_node->next;
}
}
while(p_node != q_node){
p_node = p_node->next;
q_node = q_node->next;
}
return p_node;
}
void delete_one_node(List *list, List_node *node) //删除链表的一个节点
{
//用node的next的data覆盖node的data,并让node的next指向其next的next
//然后将node的next删除
List_node *p_node = NULL;
if(list == NULL || node == NULL){
return ;
}
p_node = list->head;
if(node->next != NULL){
p_node = node->next;
node->data = p_node->data;
node->next = p_node->next;
free(p_node);
list->count--;
}else{
pop_back(list);
}
}
Boolean has_circle(List *list) //判断链表是否有环
{
List_node *p_node = NULL;
if(list == NULL || list->count < TWO || list->tail->next == NULL){
return FALSE;
}
p_node = list->head;
while(p_node != NULL){
if(p_node == list->tail->next){
return TRUE;
}
p_node = p_node->next;
}
return FALSE;
}
Boolean has_circle2(List *list, List_node **intersect);
Boolean has_circle2(List *list, List_node **intersect)
{
List_node *p_node = NULL;
List_node *q_node = NULL;
if(list == NULL || list->count < TWO){
return FALSE;
}
p_node = q_node = list->head;
while(q_node != NULL && q_node->next != NULL){
p_node = p_node->next;
q_node = q_node->next->next;
if(p_node == q_node){
return TRUE;
}
}
return FALSE;
}
//如果函数有多个返回值,只有传入某个值指针类型,才可以将其传出
List_node *find_circle_begin(List *list) //找到链表环的入口
{
List_node *p_node = NULL;
if(list == NULL || list->count < TWO || list->tail->next == NULL){
return NULL;
}
p_node = list->head;
do{
if(p_node == list->tail->next){
return p_node;
}
p_node = p_node->next;
}while(p_node != NULL);
return NULL;
}
List_node *find_circle_begin2(List *list); //找到链表环的入口
List_node *find_circle_begin2(List *list) //找到链表环的入口
{
if(!has_circle2(list, &intersect)){
return NULL;
}
}
链表的测试代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "list.h"
int main(int ac, char **av)
{
List *list = init_list(); //链表初始化
List *list1 = init_list();
List *list2 = init_list();
List *list3 = NULL;
List_node *p_node = NULL;
List_node *q_node = NULL;
int i = 0;
int result = 0;
srand(time(NULL));
for(i = 0; i < 10; ++i){
push_front(list, rand() % 100);
}
for(i = 0; i < 10; ++i){
push_front(list1, rand() % 100);
}
printf("before sort show list:\n");
print_list(list);
printf("before sort show list1:\n");
print_list(list1);
sort_list_ascend(list);
sort_list_ascend(list1);
printf("after sort show list:\n");
print_list(list);
printf("after sort show list1:\n");
print_list(list1);
list2 = merge_two_lists(list, list1);
printf("after merge show list2:\n");
print_list(list2);
printf("after merge show list:\n");
print_list(list);
printf("after merge show list1:\n");
print_list(list1);
printf("after reverse show list2:\n");
list3 = reverse_list(list2);
printf("after reverse show list3:\n");
print_list(list3);
printf("倒数第num个节点\n");
p_node = find_revise_node(list3, 5);
printf("%d\n", p_node->data);
//printf("中间节点\n");
//printf("删除一个节点\n");
//delete_one_node(list, );
//print_list(list);
printf("判断两个链表是否有交点\n");
result = is_list_intersect(list, list1);
printf("result is : %d\n", result);
q_node = find_first_common_node(list, list1);
printf("%d\n", p_node->data);
sort_list_descend(list);
print_list(list);
destroy_list(&list); //链表的销毁
destroy_list(&list1); //链表的销毁
destroy_list(&list2); //链表的销毁
return 0;
}
测试结果如下:
[root@localhost list]# ./main
before sort show list:
75 68 13 10 17 45 10 24 60 21
before sort show list1:
43 8 32 88 52 8 51 87 36 20
after sort show list:
10 10 13 17 21 24 45 60 68 75
after sort show list1:
8 8 20 32 36 43 51 52 87 88
after merge show list2:
8 8 10 10 13 17 20 21 24 32 36 43 45 51 52 60 68 75 87 88
after merge show list:
10 10 13 17 21 24 45 60 68 75
after merge show list1:
8 8 20 32 36 43 51 52 87 88
after reverse show list2:
after reverse show list3:
88 87 75 68 60 52 51 45 43 36 32 24 21 20 17 13 10 10 8 8
倒数第num个节点
13
判断两个链表是否有交点
result is : 0
13
75 68 60 45 24 21 17 13 10 10
[root@localhost list]#