資料結構——找兩個單鏈表的交叉點,並將交叉點在連結串列ls1中所處的位置打印出來
阿新 • • 發佈:2018-12-18
1、程式檔案
I、
在交叉點/src目錄下分別建立main.c、Linklist.c檔案
//main.c #include <stdio.h> #include <stdlib.h> //包括rand()、srand()、abs()等函式 #include <time.h> #include "LinkList.h" int main() { //連結串列ls1 List *ls1 = CreateList(); //連結串列ls2 List *ls2 = CreateList(); if (NULL == ls1 || NULL == ls2) { printf ("建立失敗\n"); } printf ("建立成功!\n"); int i; int num; srand((unsigned int)time(NULL)); //連結串列ls1長度隨機指定(10,20) int len1 = rand()%11 + 10 ; for (i = 0; i < len1; i++) { //尾插 Insert_Last(ls1, rand()%10 + 1); } //連結串列ls2 = 隨機的長度(1,10) + ls1後面擷取的一段 int len2 = rand()%10 + 1; for (i = 0; i < len2; i++) { Insert_Last(ls2, rand()%10 + 1); } Node *p1 = ls1->head->next; //p1隨機指向的結點範圍(15,20) for (i = 0; i < rand()%16 + 5; i++) { p1 = p1->next; } Node *p2 = ls2->head->next; //p2先指向ls2的尾結點 while (p2->next) { p2 = p2->next; } //p1隨機指向的ls1中的那個結點的地址賦給p2,即插到ls2的鏈尾 //以此構造交叉鏈 p2->next = p1->next; Display(ls1); Display(ls2); //交叉點 int pos = Find_Intersection(ls1, ls2); printf ("交叉點在連結串列ls1中的位置為:%d\n", pos); Destory(ls1); Destory(ls2); return 0; }
//LinkList.c #include <stdio.h> #include "LinkList.h" #include <stdlib.h> //建立連結串列 List *CreateList(void) { List *ls = (List*)malloc(sizeof(List)/sizeof(char)); if (NULL == ls) { return NULL; } ls->head = (Node*)malloc(sizeof(Node)/sizeof(char)); if (NULL == ls->head) { free(ls); return NULL; } ls->head->next = NULL;//空連結串列 return ls; } //尾插 BOOL Insert_Last(List *ls, Data data) { if (NULL == ls) { return ERROR; } Node *node = (Node *)malloc(sizeof(Node)/sizeof(char)); if (NULL == node) { return ERROR; } node->data = data; node->next = NULL; Node *tmp = ls->head;//頭結點 //作表示式時,取指標變數中存放的地址值 while (tmp->next) { tmp = tmp->next; } //tmp->next相當於int *p = &a中的p tmp->next = node; return TRUE; } //找交叉點 int Find_Intersection(List *ls1, List *ls2) { if (ls1 == NULL || ls2 == NULL) { return -1; } Node *p1 = ls1->head->next; Node *p2 = ls2->head->next; int len1 = 1; int len2 = 1; int count = 0; //分別統計長度 while (p1->next != NULL) { len1++; p1 = p1->next; } while (p2->next != NULL) { len2++; p2 = p2->next; } p1 = ls1->head->next; p2 = ls2->head->next; if (len1 >= len2) { int num = len1 - len2; count = num; while (num > 0) { p1 = p1->next; num--; } //這裡直接判斷p1 和 p2是否相等,因為較短連結串列的頭結點可能就是交點 while (p1 != p2) { p1 = p1->next; p2 = p2->next; count++; } return count+1; } else { int num = len2 - len1; while (num > 0) { p2 = p2->next; num--; } //這裡直接判斷p1 和 p2是否相等,因為較短連結串列的頭結點可能就是交點 while (p1 != p2) { p1 = p1->next; p2 = p2->next; count++; } return count; } } //列印 void Display(List *ls) { if (NULL == ls) { return; } Node *tmp = ls->head->next;//第一個結點 while (tmp) { printf ("%-4d", tmp->data); tmp = tmp->next; } printf("\n"); } //銷燬 void Destory(List *ls) { if (NULL == ls) { return; } Node *tmp = ls->head; //取0x1000中存放的地址/取首結點的地址、或稱取頭結點中的地址值 while (tmp->next) { Node *p = tmp->next; tmp->next = p->next; free(p); } free(ls->head); free(ls); }
II、
在交叉點/include目錄下建立Linklist.h檔案
#ifndef _LINKLIST_H_ #define _LINKLIST_H_ typedef enum {TRUE, FALSE, ERROR} BOOL; typedef int Data; //每一個結點中應包含一個指標變數,用它來存放下一結點的地址 typedef struct _node { //資料域 Data data; //指標域 struct _node *next; }Node; typedef struct _list { //頭節點 Node *head; }List; //建立連結串列 List *CreateList(void); //尾插 BOOL Insert_Last(List *ls, Data data); //找交叉點 int Find_Intersection(List *ls1, List *ls2); //列印 void Display(List *ls); //銷燬 void Destory(List *ls); #endif //_LINKLIST_H
III、
在“交叉點”目錄下建立Makefile檔案
src1 = $(wildcard ./src/*.c)
obj1 = $(patsubst ./src/%.c, ./obj/%.o, $(src1))
target = ./bin/a.out
all:$(target)
$(target):$(obj1)
gcc $(^) -o $(@)
$(obj1):./obj/%.o:./src/%.c
gcc -c $(^) -I ./include -o $(@) -g
.PHONY:clean all
clean:
-rm -rf $(target) $(obj1)
2、測試結果
[email protected]:/交叉點# ./bin/a.out
建立成功!
10 6 10 4 6 7 9 6 4 10 2 8 10 8 4 10 3 5 4
6 4 10 2 8 10 8 4 10 3 5 4
交叉點在連結串列ls1中的位置為:9