/*************************************************************************
> File Name: ctr_list.c
> Author: khalil
> Mail: [email protected]
> 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
【2015/11/21】 數據結構學習日誌_Day17 雙端鏈表
版權聲明:本文爲博主原創文章,未經博主允許不得轉載。 https://blog.csdn.net/hsgwpj/article/details/50045843
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.