您的位置:首页 > 理论基础 > 数据结构算法

数据结构之单链表的实现

2016-03-29 23:58 429 查看
单链表:

特点: 链表的链接方向是单向的;

链表是由节点构成,每个节点由两部分(节点数据和指向下一节点的指针);

>

链表的结构体及变量重定义如下:

#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]#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: