數據結構之鏈表

題目:

1.已知單鏈表L是一個遞增有序鏈表,設計一個算法,刪除表中data值在大於等於min並且小於等於max之間的節點,同時釋放刪除節點的空間,分析時間複雜度
2.設計一個算法就地逆置單鏈表
3.已知三個遞增有序單鏈表A,B,C,長度分別爲m,n和p設計一個算法使鏈表A 僅包含三個表中均包含的數據元素,且沒有重複,並釋放無用節點。限定算法的時間複雜度爲O(m+n+p)

鏈表結構體

typedef struct node {
  int data;
  struct node *next;
} LNode, *LinkList;


代碼

#include "stdio.h"
#include "stdlib.h"

typedef struct node {
  int data;
  struct node *next;
} LNode, *LinkList;


//初始化數據,尾插法
LinkList InitList(){

	 LinkList head,p; 
	 int i = 0; 
	 head = (LinkList)malloc(sizeof(LNode));
	 head->next = NULL;

	 printf("輸入負數結束輸入:\n");

	 for(scanf("%d",&i);i > -1;scanf("%d",&i)){ 
		  p = (LinkList)malloc(sizeof(LNode));  
		  p->data = i;  
		  p->next = head->next;  
		  head->next = p;  
	 }

	return head;
}

//初始化數據,頭插法
LinkList Init(){
	 LinkList p,r;
	 LinkList list = NULL;
	 int i;
 
	 printf("輸入負數結束輸入:\n");

	 for(scanf("%d",&i);i > -1;scanf("%d",&i)) {
	  p = (LinkList)malloc(sizeof(LNode));
	  p->data = i;
	  p->next = NULL;
	  if(!list) {
		 list = p;
	   } else {
		 r->next = p;
		}
		 r = p;
	  }
	  return list;
}

void printList(LinkList root){
	
	LinkList list = root;
	//list = list->next; //尾插法,取消註釋
	while(list) {  
	   printf("%d ->",list->data);  
	   list = list->next;
	 }  
	printf("NULL\n");
}

//刪除第一個data= value的節點
LinkList ListDelNode(LinkList root,int value){
	LinkList list,pre;
	list = pre = root;
	while(list){
		if(list->data == value){

			if(list == root){
				root = root->next;
				free(list);				//free node
				break;                  //break loop
			}

			pre->next = list->next;
			free(list);
			break;					
		}
		
		if(list != root)
			pre = pre->next;
		list = list->next;	
	}
	return root;

}

//刪除data =min ~ max 的節點
LinkList ListDelRange(LinkList root,int min,int max){
	LinkList list,pre;
	list = pre = root;
	while(list){
		if(list->data > max) break;  //break loop
		if(list->data >= min){
			if(list == root){
				root = root->next;
				list = pre = root;
				continue;
			}
			pre->next = list->next;
			free(list);	
			list = NULL;
		}

		if(list == NULL){                  
			list = pre->next;		//if free list
			continue;
		}

		if(list != root)
			pre = pre->next;
		list = list->next;	
	}
	return root;
}


LinkList inverse(LinkList root){
	LinkList next,pre;
	pre =  root;

	if(!root->next)       //only 1 node 
		return root;

	root = root->next;        //only 2 nodes
	pre->next = NULL;

	if(!root->next){
		root->next = pre;
		return root;
	}

	next = root->next;

	while(next){
		root->next = pre;
		pre = root;
		root = next;
		next = root->next;
	}
	root->next = pre;
	return root;
}

//判斷三個數中的最小值
int min3(int a,int b,int c){
	a =  a<b?a:b;
	a =  a<c?a:c;
	return a;
}

int jugde(LinkList node){
		if(node) 
			return node->data;
		else 
			return 999999;            //返回一個比a,b,c鏈表最大值都大的數
}

//合併 a,b,b三個順序表,去重複
LinkList merge3(LinkList a,LinkList b,LinkList c){
	LinkList head,p,q;
	int temp;
	head = NULL;

	while(a || b || c){
		temp = min3(jugde(a),jugde(b),jugde(c));
		p = (LinkList)malloc(sizeof(LNode));
		p->data = temp;
		p->next = NULL;
		if(!head) head = p;
		else q->next = p;
		q = p;

		if(a && a->data == temp)
			a = a->next;//a = a == NULL ? a:a->next;   //修改
		if(b && b->data == temp)
			b = b->next;
		if(c && c->data == temp)
			c = c->next;
	}

	return head;
}

//合併 a,b,c三個順序表存到a中,去重複,O(m+n+p)
void merge2A(LinkList *A,LinkList b,LinkList c){
	LinkList a,p,a_pre;
	int temp;
	a_pre = a = *A;				//如果直接用*A,會改變傳入的表a,因爲用了a的地址

	while(a || b || c){

		temp = min3(jugde(a),jugde(b),jugde(c));	

		if(a && a->data == temp){			//如果a含有這個元素,並判斷b,c是否具有這個元素
					a = a->next;				//下移
					if(a != (*A)->next)
						a_pre = a_pre->next;
			if(b && b->data == temp){           //b不爲空,且b->data = temp
				p = b == NULL?NULL:b->next;
				free(b);
				b = p;							//釋放b,併到下一個
			}
			
			if(c && c->data == temp){           //同上
				p = c == NULL?NULL:c->next;
				free(c);
				c = p;							
			}
			
		}else{									//如果a不含這個元素,並注意a是否爲NULL

			if(b && b->data == temp){			//b含有
				p = b == NULL?NULL:b->next;
				if(a_pre == a){					//如果 a_pre = a,表面在數組a前面插入數字
					b->next = a;
					*A = b;
					a = a_pre = b;
					b = p;
					if(c && c->data == temp){		//如果c也含有,則free
						p = c->next;
						free(c);
						c = p;
					}
					goto label1;
				}
				if(a && temp < a->data){		//a不爲NULL,且 temp< a->data
					b->next = a;
					a_pre->next = b;
					a_pre = b;
				}else{
					b->next = a==NULL?NULL:a->next;
					if(a) a->next = b;
					else  a_pre->next = b;
					//free(b)	;                      //不能free
				}

				b = p;
				
				if(c && c->data == temp){		//如果c也含有,則free
					p = c->next;
					free(c);
					c = p;
				}
				a = a==NULL?NULL:a->next;				//a下移
				a_pre = a_pre->next == NULL ? a_pre:a_pre->next;		//a_pre 下移
			}
			
			label1:
			if(c && c->data == temp){					//如果只有c含有
					p = c == NULL?NULL:c->next;
					if(a_pre == a){					//如果 a_pre = a,表示在數組a前面插入數字
						b->next = a;
						*A = b;
						a = a_pre = b;
						b = p;
						continue;
					}

					if(a && temp < a->data){
						c->next = a;
						a_pre->next = c;
						a_pre = c;
					}else{
						c->next = a==NULL?NULL:a->next;
						if(a) a->next = c;
						else  a_pre->next = c;
					}
					c = p;
					a = a==NULL?NULL:a->next;						//a下移
					a_pre = a_pre->next == NULL ? a_pre:a_pre->next;		//a_pre 下移
				}
		}
		
	}
}

void main(){
	/*
	LinkList L;
	L = Init();
	//L = ListDelNode(L,2);
	L = ListDelRange(L,2,4);  //第一題
	printList(L);
	printf("逆置線性表:\n");  //第二題
	L = inverse(L);
	printList(L);
	*/

	//第三題
	LinkList a,b,c,out;
	a = Init();
	b = Init();
	c = Init();
	merge2A(&a,b,c);
	printList(a);
	/*
	out = merge3(a,b,c);
	printList(out);
	*/
		
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章