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

【2015/11/21】 数据结构学习日志_Day17 双端链表

2015-11-26 00:42 375 查看
/*************************************************************************
> File Name: ctr_list.c
> Author: khalil
> Mail: hsgwpj@gmail.com
> Created Time: Sat 21 Nov 2015 09:11:34 AM CST
************************************************************************/

#include<stdio.h>
#include<string.h>
#include<stdlib.h>

// 《C语言接口与实现》 *
//  C的面向对象: lua
//  redis 键值对数据库

//比较优秀的网站:
//    stackoverflow
//    sourceforge

#if 1
//为bool类型宏定义
#define true     (1)
#define false    (0)

#define ZERO     (0)
#define ONLY_ONE (1)
#define TWO      (2)
#define get_data_size()  ((unsigned long)&(((List_node *)0)->next))

//链表控制信息:
//
// 1.头、尾节点位置
// 2.链表元素数量
//
//链表节点信息:
//
// 1.数据域
// 2.指针域

//节点:
typedef struct List_node
{
int               data;     //数据域
struct List_node *next;     //指针域
}List_node;

//控制:
typedef struct List
{
struct List_node *head;     //指向链表头部
struct List_node *tail;     //指向链表尾部
int              count;     //链表节点数量
}List;

typedef unsigned char bool;

static void *Malloc(size_t size); //包裹函数
static List_node *create_node(void);//创建节点
static void swap(void *a, void *b, int len);//交换data
static void reverse_show_list_node(List_node *p);//组件

static void swap(void *a, void *b, int len)
{
void *tmp = Malloc(len);
memcpy(tmp, a, len);
memcpy(a, b, len);
memcpy(b, tmp, len);

free(tmp);
}
static List_node *create_node(void)
{
List_node *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, "Memory Full!\n");
exit(1);
}
return result;
}

static void reverse_show_list_node(List_node *p)
{
if(p){
reverse_show_list_node(p->next);
printf("%d\t", p->data);
}
}

//链表接口:
List        *init_list(void);                       //链表的初始化
void        destory_list(List **);                  //链表的销毁
bool        push_front(List *list, int value);      //头部插入
bool        push_back (List *list, int value);      //尾部插入
bool        pop_front (List *list);                 //头部删除
bool        pop_back  (List *list);                 //尾部删除
void        show_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        *merge_two_lists_recure(List *list1, List *list2);  //合并两个有序链表(递归)
List_node   *find_revise_node(List *list, int num);             //找到链表的倒数第num个节点
List_node   *find_mid_node   (List *list);                      //找到链表的中间节点
List        *reverse_list    (List *list);                      //逆置一个链表
List        *list_dump       (List *list);                      //链表拷贝
void        reverse_show_list(List *list);                      //逆序输出一个链表
bool        is_lists_intersect    (List *list1, List *list2);   //判断链表是否相交
List_node   *get_first_common_node(List *list1, List *list2);   //得到第一个交点
void        delete_one_node       (List *List, List_node *node);//在O(1)的时间复杂度下删除节点
bool        has_circle            (List *list, List_node **intersect);                 //判断一个链表是否有环
List_node   *find_circle_first_node(List *list);                //找到带环链表的环入口点

////////////////////////////////////////////////////////////
//////////////////////  接口实现  //////////////////////////
////////////////////////////////////////////////////////////

List        *init_list(void)                        //链表的初始化
{
List *list = (List *)Malloc(sizeof(List));
//    head && tail && count --> NULL/0
bzero(list, sizeof(List));
return list;
}

void        destory_list(List **list)                   //链表的销毁
{
if(list == NULL || *list == NULL){
return;
}
//遍历释放空间
//List *p_list = *list;
//List_node *p_node = p_list->head;
//List_node *q_node = NULL;
//删除链表节点信息
//while(p_node){
//    q_node = p_node;
//    p_node = p_node->next;
//    free(q_node);
//}

//删除链表节点信息
while((*list)->count){
pop_front(*list);
}
//删除链表控制信息
free(*list);
*list = NULL;
}

bool        push_front(List *list, int value)       //头部插入
{
if(list == NULL){
return false;
}

//创建节点并赋值
List_node *node = create_node();
node->data = value;

if(list->count == ZERO){

//  case 1:空链表
//  head && tail -> node_1; count = 1

list->head = list->tail = node;
}else{

// case 2:非空链表
// head -> node_1 ; tail -> node_n; count = n + 1

node->next = list->head;
list->head = node;
}
list->count++;
return true;
}

bool        push_back (List *list, int value)       //尾部插入
{
if(list == NULL){
return false;
}

List_node *node = create_node();
node->data = value;

if(list->count == ZERO){
//case 1: 空链表
list->head = list->tail = node;
}else{
//case 2: 非空链表
list->tail->next = node;
list->tail = node;
}
list->count++;
return true;
}

bool        pop_front (List *list)                  //头部删除
{
if(list == NULL || list->count == ZERO){
return false;
}

List_node *p_node = list->head;

//case 1:只有一个节点
//case 2:大于一个节点

if(list->count == ONLY_ONE){
list->head = list->tail = NULL;
}else{
list->head = list->head->next;
}
free(p_node);
list->count--;
return true;
}

bool        pop_back  (List *list)                  //尾部删除
{
if(list == NULL || list->count == ZERO){
return false;
}

List_node *p_node = list->head;

//case 1:只有一个节点
//case 2:大于一个节点

if(list->count == ONLY_ONE){
list->head = list->tail = NULL;
free(p_node);
}else{
//遍历一遍链表 将p_node指向倒数第二个节点
while(p_node->next != list->tail){
p_node = p_node->next;
}
free(list->tail);
list->tail = p_node;
p_node->next = NULL;
}
list->count--;
return true;
}

void        show_list (List *list)                  //显示链表信息
{
if(list != NULL && list->count != ZERO){
List_node *p_node = list->head;
for( ; p_node; p_node = p_node->next ){
printf("%d\t",p_node->data);
}
printf("\n");
}
}

void        sort_list_ascend (List *list)           //升序排列
{
if(list == NULL || list->count < TWO){
return ;
}

List_node *p_node = NULL;
List_node *q_node = NULL;

unsigned long data_size = 0;
data_size = get_data_size();//求数据区域大小

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, q_node, data_size);
}
}
}
}

void        sort_list_descend(List *list)           //降序排列
{
if(list == NULL || list->count < TWO){
return ;
}

List_node *p_node = NULL;
List_node *q_node = NULL;

unsigned long data_size = 0;
data_size = get_data_size();//求数据区域大小

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, q_node, data_size);
}
}
}
}

int         get_list_count   (List *list)           //得到链表节点数量
{
if(list == NULL){
return -1;
}

return list->count;
}

List        *merge_two_lists       (List *list1, List *list2)   //合并两个有序链表
{
List *result = NULL;
if(list1 == NULL || list2 == NULL){
return result;
}

result = init_list();
List_node *p = list1->head;
List_node *q = list2->head;

// 如果两个链表都没有遍历完,则进行比较
while(p && q){
if(p->data < q->data){
push_back(result, p->data);
p = p->next;
}else{
push_back(result, q->data);
q = q->next;
}
}

//如果有一个比较完了,把另一个直接进行拷贝
if(p == NULL){
while(q){
push_back(result, q->data);
q = q->next;
}
}
if(q == NULL){
while(p){
push_back(result, p->data);
p = p->next;
}
}

return result;
}

List        *merge_two_lists_recure(List *list1, List *list2)   //合并两个有序链表(递归)
{
//使用组件来进行递归输出!
}

List_node   *find_revise_node(List *list, int num)             //找到链表的倒数第num个节点
{
if(list == NULL || num <= 0 && num > list->count){
return NULL;
}

List_node *p = list->head;
int time = list->count - num;

while(time--){
p = p->next;
}

return p;
}

List_node   *find_mid_node   (List *list)                      //找到链表的中间节点
{
// 1.快慢指针:
//  一个一次走两步 一个一次走一步
//
// 2.count/2找指针

if(list == NULL){
return NULL;
}

#if 1
List_node *p = list->head;
List_node *q = p;

while(p){
p = p->next;
if(p){
p = p->next;
}
q = q->next;
}

return q;
#endif

#if 0
List_node *p = list->head;
int time = list->count >> 1;
while(time--){
p = p->next;
}
return p;
#endif
}

List        *reverse_list    (List *list)                     //逆置一个链表
{
if(list == NULL || list->count < TWO){
return list;
}
#if 0
//创建一个新的链表 与数组
int datas[list->count];
List_node *p = list->head;
List *result = init_list();
int i = 0;
for( ; i < list->count; ++i ){
datas[i] = p->data;
p = p->next;
}

for( ; i; --i ){
push_back(result, datas[i-1]);
}
return result;
#endif

#if 1
//不创建新链表 使用三个指针进行赋值
if(list->count == TWO){
//如果只有两个节点
list->tail->next = list->head;
list->head->next = NULL;
return list;
}

List_node *p = list->head;
List_node *q = p->next;
List_node *r = q->next;
p->next = NULL;

do{
q->next = p;
p = q;
q = r;
r = r->next;
}while(r);

q->next = p;

swap(&(list->head), &(list->tail), sizeof(List_node *));
return list;
#endif
}

List        *list_dump       (List *list)                      //链表拷贝
{
if(list == NULL){
return NULL;
}

List *result = init_list();
List_node *p = list->head;

while(p){
push_back(result, p->data);
p = p->next;
}

return result;
}

void        reverse_show_list(List *list)                      //逆序输出一个链表
{
if(list == NULL){
return;
}
//递归逆序输出比较好
reverse_show_list_node(list->head);
//使用组件来输出
}

bool        is_lists_intersect    (List *list1, List *list2)   //判断链表是否相交
{
if (list1 == NULL || list2 == NULL){
return false;
}

return (list1->tail == list2->tail);
}

List_node   *get_first_common_node(List *list1, List *list2)   //得到第一个交点
{
if(! is_lists_intersect(list1, list2)){
return NULL;
}

int list1_len = list1->count;
int list2_len = list2->count;
int distance  = 0;

List_node *p = list1->head;
List_node *q = list2->head;

//将始末差距移动到相同距离
if(list1_len > list2_len){
distance = list1_len - list2_len;
while(distance--){
p = p->next;
}
}else{
distance = list2_len - list1_len;
while(distance--){
q = q->next;
}
}

//依次对对应节点进行判断是否相等,相等则为第一个相交界点
while(p != q){
p = p->next;
q = q->next;
}

return p;
}

void        delete_one_node       (List *list, List_node *node)//在O(1)的时间复杂度下删除节点
{
if(list == NULL || node == NULL){
return ;
}

List_node *p = NULL;
if(node != list->tail){
//不是末尾
p = node->next;
node->data = p->data;
node->next = p->next;
free(p);
list->count--;
}else{
//是末尾
pop_back(list);
}
}

bool        has_circle            (List *list, List_node **intersect)                 //判断一个链表是否有环
{
if(list ==NULL || list->count < TWO){
return false;
}
//快慢指针跑环
//如果有环的话两者一定会相遇
List_node *fast = list->head;
List_node *slow = fast;

do{
fast = fast->next;
fast = fast->next;
slow = slow->next;
if(fast == slow){
if(intersect){
//将相交节点赋值给intersect
*intersect = fast;
}
return true;
}
}while(fast && fast->next);

return false;
}

List_node   *find_circle_first_node(List *list)                //找到带环链表的环入口点
{
List_node *intersect = NULL;
if(! has_circle(list, &intersect)){
return NULL;
}

//转化为求两个相交链表的第一个结点的问题
List_node *list1_head = list->head;
List_node *list2_head = intersect->next;

//求得二个链表的长度
List_node *p = list1_head;
List_node *q = list2_head;

int list1_len = 0;
int list2_len = 0;
int distance  = 0;

while(p != intersect){
list1_len++;
p = p->next;
}

while(q != intersect){
list2_len++;
q = q->next;
}

p = list1_head;
q = list2_head;

//移动较长的链表 移动距离为两个长度的差
if(list1_len > list2_len){
distance = list1_len - list2_len;
while(distance--){
p = p->next;
}
}else{
distance = list2_len - list1_len;
while(distance--){
q = q->next;
}
}

while(p != q){
p = p->next;
q = q->next;
}

return q;
}

/////////////////////////////// 测试 //////////////////////////////////////

int main(int argc, char **argv)
{
List* list = init_list();   //initialize
List* list1 = init_list();
List* tmp = NULL;
int i = 0;
for (i = 0; i < 10; ++i){
push_back(list, rand() % 200);
push_back(list1, rand() % 233);
}
printf("list:\n");
sort_list_ascend(list);
show_list(list);
printf("list1:\n");
sort_list_ascend(list1);
show_list(list1);

printf("\nmerge_result:\n");
List* result = merge_two_lists(list, list1);
show_list(result);

List_node *p = find_revise_node(list, 1);
printf("\nrevise_1_p:%d\n", p->data);

List_node *mid = find_mid_node(list);
printf("mid:%d\n", mid->data);

reverse_list(list1);
printf("reve:\n");
show_list(list1);

tmp = list_dump(list1);
printf("copy:\n");
show_list(tmp);
printf("reve_show:\n");
reverse_show_list(tmp);

destory_list(&tmp);
destory_list(&list);
destory_list(&list1);
destory_list(&result);
return 0;
}
#endif
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: