1. 程式人生 > >對於單向連結串列的10幾種常用演算法

對於單向連結串列的10幾種常用演算法

list.c檔案如下

#include "list.h"

/*返回head連結串列POS節點的位置*/
LINK list_moov_pos(LINK head,int pos){
	LINK node = head;
	while(--pos) node = node->pNext;  
	return node;
}
/*求連結串列長度*/
int list_length(LINK *head){
	LINK node = *head;
	int i = 0;
	while(NULL != node){
		i++;
		node = node->pNext;
	}
	return i;
}
/* 判斷連結串列是否為空 */
bool list_empty(LINK *head){
	LINK node = *head;
	if(NULL == node)
		return true;
	else
		return false;
}
/* 對連結串列進行氣泡排序 */
LINK list_sort(LINK *head){
	LINK node = *head;
	LINK p = NULL;
	LINK q = NULL;
	LINK cache = (LINK)malloc(sizeof(LIST_DATA));
	if(NULL == cache) exit(-1);
	for (p = node; p != NULL; p = p->pNext){
		for (q = p->pNext; q != NULL; q=q->pNext){
			if ((p->data).nume > (q->data).nume)
			{
				cache->data = p->data;
				p->data = q->data;
				q->data = cache->data;
			}
		}
	}
	free(cache);
	return node;
}
/*刪除連結串列head中第POS個節點的資料*/
bool list_pos_dele(LINK *head, int pos){
	if(NULL == *head ||(0 < pos && pos > list_length(head)))
		return false;
	if(1 == pos){
		LINK node = *head;
		*head = node->pNext;
		free(node);
	}else{ 
		LINK pre_node = NULL, now_node= NULL;
		pre_node = list_moov_pos(*head,pos-1);
		now_node = list_moov_pos(*head,pos);
		pre_node->pNext = now_node ->pNext;
		free(now_node);
	}
	return true;
}
/*刪除連結串列head頭POS個刪除*/
bool list_head_dele(LINK *head ,int pos){
	if(NULL == *head || (0 < pos && pos > list_length(head)))
		return false;
	LINK node = NULL;
	node = list_moov_pos(*head, pos);
	*head=node->pNext;
	free(node);
	return true;
}
/*頭新增*/
void list_head_add(LINK *head, DATA data){
	if(*head == NULL){  
		(*head) = (LINK)malloc(sizeof(LIST_DATA));
		if(NULL == *head) exit(-1);
		(*head)->data = data;
		(*head)->pNext = NULL; 	
	}else{
		LINK add_node = NULL;
		add_node = (LINK)malloc(sizeof(LIST_DATA));	
		if(NULL == add_node) exit(-1);
		add_node->data = data;
		add_node->pNext = *head;
		*head = add_node; 	
	}
}
/*尾巴新增*/
void list_end_add(LINK *head, DATA data){
	if(*head == NULL){  
		(*head) = (LINK)malloc(sizeof(LIST_DATA));  
		if(NULL == *head) exit(-1);        
		(*head)->data = data; 
		(*head)->pNext = NULL;	  	
	}else{
		LINK node = *head, node_add = NULL; 
		while(node->pNext != NULL) 
			  node = node->pNext;
		node_add = (LINK)malloc(sizeof(LIST_DATA));
		if(NULL == node_add) exit(-1);
		node_add->data = data;
		node_add->pNext = NULL;
		node->pNext = node_add;				 
	}
} 
/*任意改動*/
bool list_random_change(LINK *head, DATA data, int pos){
	if(NULL == *head || (0 < pos && pos > list_length(head)))
		return false;
	LINK node = NULL;
	node = list_moov_pos(*head,pos);
	node->data = data;
	return true;
}
/*任意節點前面插入資料*/
bool list_random_insert(LINK *head, DATA data, int pos){
	if(NULL == *head || (0 < pos && pos > list_length(head)))
		return false;	
	if(pos==1){
		LINK node = NULL;
		node = (LINK)malloc(sizeof(LIST_DATA));
	    if(NULL == node) exit(-1);                                  
		node->data = data; //將name賦值給結構體指標*head中的name。
		node->pNext=*head;
		*head = node;
	} else{
       LINK node = NULL,add_node = NULL;
       add_node = (LINK)malloc(sizeof(LIST_DATA));
       if(NULL == add_node) exit(-1);
       node = list_moov_pos(*head ,pos-1);
       add_node->data = data;      
       add_node->pNext = node->pNext;
       node->pNext =add_node;	  	
 	}	
 	return true;
}
/*連結串列head1 和head2 各自有序,合併成一個連結串列依然有序(遞迴方法)*/
LINK list_merge_recursive(LINK *head1, LINK *head2) {
     LINK head = NULL;
     LINK node1 = *head1;
     LINK node2 = *head2;
     if(node1 == NULL) return *head2;
     if(node2 == NULL) return *head1;

     if(node1->data.nume <= node2->data.nume) {
         head = node1;
         head->pNext = list_merge_recursive(&(*node1).pNext, &node2);
     }else {
         head = node2;
         head->pNext = list_merge_recursive(&node1, &(*node2).pNext);
     }
     return head;
}
/*將連結串列逆序*/
LINK list_reverse(LINK *head){
	LINK node = *head;
    if( node == NULL || (*node).pNext == NULL || (*node).pNext->pNext == NULL)  
       return node;   /*連結串列為空或只有一個元素則直接返回*/
 
    LINK t = NULL;
    LINK q = node;
    LINK p = (*node).pNext;
 
    while(q != NULL){        
      	t = q->pNext;
      	q->pNext = p;
      	p = q;
      	q = t;
    }
    /*此時q指向原始連結串列最後一個元素,也是逆轉後的連結串列的表頭元素*/
    (*node).pNext->pNext = NULL; /*設定連結串列尾*/
    (*node).pNext = p;           /*調整連結串列頭*/

    DATA data;
    data = node->data;
    list_end_add(&node,data);
    list_pos_dele(&node,1);
    return node;
}
/*連線2個連結串列*/
LINK list_concatenate(LINK *head1,LINK *head2){
	if(*head1 == NULL) return *head2;
	if(*head2 == NULL) return *head1;
    LINK node = *head1;
    while(node->pNext != NULL)
        node=node->pNext;
    node->pNext = *head2;
    return *head1;
}
/*銷燬連結串列*/
void list_free(LINK *head){
    while(*head != NULL){
        list_free(&(*head)->pNext);
        free(*head);
        *head = NULL;
    }
}
list.h檔案如下

#ifndef LIST_H
#define LIST_H
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <stdbool.h>

typedef struct list{
	char name[1024];
	int  nume;
}DATA;

typedef struct list_all{
	DATA data;
	struct list_all *pNext;
}LIST_DATA;

typedef LIST_DATA* LINK;

#include "list.h"

/*返回head連結串列POS節點的位置*/
LINK list_moov_pos(LINK head,int pos);
/*求連結串列長度*/
int list_length(LINK *head);
/* 判斷連結串列是否為空 */
bool list_empty(LINK *head);
/* 對連結串列進行氣泡排序 */
LINK list_sort(LINK *head);
/*刪除連結串列head中第POS個節點的資料*/
bool list_pos_dele(LINK *head, int pos);
/*刪除連結串列head頭POS個刪除*/
bool list_head_dele(LINK *head ,int pos);
/*頭新增*/
void list_head_add(LINK *head, DATA data);
/*尾巴新增*/
void list_end_add(LINK *head, DATA data);
/*任意改動*/
bool list_random_change(LINK *head, DATA data, int pos);
/*任意節點前面插入資料*/
bool list_random_insert(LINK *head, DATA data, int pos);
/*連結串列head1 和head2 各自有序,合併成一個連結串列依然有序(遞迴方法)*/
LINK list_merge_recursive(LINK *head1, LINK *head2);
/*將連結串列逆序*/
LINK list_reverse(LINK *head);
/*連線2個連結串列*/
LINK list_concatenate(LINK *head1,LINK *head2);
/*銷燬連結串列*/
void list_free(LINK *head);

#endif

main.c檔案如下

#include "list.h"

LINK head = NULL;

void add_head()//往頭新增資料
{
  int i;
  DATA node;
  for(i = 0; i < 5; i++){//連續新增5個數據
    sprintf(node.name,"add head %d\0",i);
    node.nume = i;
    list_head_add(&head,node); 
  }
}

void add_tail()//往尾新增資料
{
  int i;
  DATA  node;
  for(i = 0; i < 5; i++){//連續新增5個數據
    sprintf(node.name,"add tail %d\0",i);
    node.nume = i;
    list_end_add(&head,node); 
  }
}

void add_arbitrarily(int pos)//任意插入
{
  int i;
  DATA node;
  //設定要插入的資料
  strcpy(node.name,"arbitrarily");
  node.nume = 100;
  //執行
  list_random_insert(&head,node,pos);
}

void Any_change(int pos)//任意改動
{
  int i;
  DATA node;
  //新資料
  strcpy(node.name,"Any change");
  node.nume = 101;
  //執行
  list_random_change(&head,node,pos);
}

void printf_data(LINK *head)
{
  LINK node = *head;
  while(node != NULL){
    printf("name=[%s] nume=[%d]\n",node->data.name,node->data.nume);
    node = node->pNext;
  }
  printf("\n");
}

int main(int argc, char const *argv[])
{
    assert(head == NULL);//條件測試
    printf("========往頭部新增資料=======1\n");
    add_head();
    printf_data(&head);

    printf("==========求連結串列長度=========2\n");
    int len = 0;
    len = list_length(&head);
    printf("len = %d\n",len);
  
    printf("===========尾部新增==========3\n");
    add_tail();
    printf_data(&head);

    printf("====對連結串列進行氣泡排序=====4\n");
    head = list_sort(&head);
    printf_data(&head);

    printf("=========任意節點前面插入========5\n");
    add_arbitrarily(1);//往第一個節點前面插入資料
    printf_data(&head);

    add_arbitrarily(4);//往第四個節點前面插入資料
    printf_data(&head);

    printf("======任意節點資料改動=======6\n");
    Any_change(1);
    printf_data(&head);

    Any_change(3);
    printf_data(&head);

    printf("========刪除頭N個數據========7\n");
    list_head_dele(&head,2);//刪除頭2個
    printf_data(&head);

    printf("=====刪除第POS位上的資料=====8\n");
    list_pos_dele(&head,3);//刪除第3個
    printf_data(&head);

    printf("=============倒序============9\n");
    head = list_reverse(&head); /*倒序*/
    printf_data(&head); 

    printf("=====按nume編號合併連結串列======10\n");
    int i;
    LINK test = NULL;
    DATA node;
    //生成新連結串列
    for(i = 0; i < 5; i++){//連續新增5個數據
      sprintf(node.name,"list merge recursive %d\0",i);
      node.nume = i;
      list_end_add(&test,node); 
    }
    //head = list_merge_recursive(&head,&test);/*合併head 和 test 連結串列*/
   // printf_data(&head);

    printf("====直接按順序連線2個連結串列====11\n");
    /*按順序連線2個連結串列*/
    head = list_concatenate(&test,&head);//test 在前
    printf_data(&head); 

    printf("======判斷連結串列是否為空=======12\n");
    if(list_empty(&head))
      	printf("list is NULL\n");
    else
      	printf("list don't NULL\n");

    printf("============銷燬連結串列=========13\n");
    list_free(&head);//銷燬連結串列
    printf_data(&head); 

    printf("======判斷連結串列是否為空=======14\n");
    if(list_empty(&head))
      	printf("list is NULL\n");
    else
      	printf("list don't NULL\n");

}