題目:
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);
*/
}