数据结构代码练习DAY2
1
在DAY1的基础上增加了一些函数
#include <stdio.h>
#include <malloc.h>typedef struct LinkNode
{int data;struct LinkNode* next;
}LNode;void CreataLNode(LNode*& L, int a[], int n)
{L = (LNode*)malloc(sizeof(LNode));LNode* r;r = L;LNode* node;for (int i = 0; i < n; i++)//用for循环将0-(n-1)下标的元素放进链表{node = (LNode*)malloc(sizeof(LNode));node->data = a[i];r->next = node;r = node;}r->next = NULL;//尾插法记得最后置空
}void PrintALL(LNode* L)
{LNode* p = L->next;while (p != NULL){printf(" %d ", p->data);p = p->next;}
}void Delete_x(LNode*& L, int x)
{LNode* pre, * p;pre = L;p = L->next;while (p != NULL){if (p->data == x){pre->next = p->next;free(p);p = pre->next;//p向后移}else{pre = p;p = p->next;}}
}void Insert_i(LNode*& L, int i,int e)
{if (L->next == NULL)return;else{LNode* pre = L;LNode* p = L->next;int count = 0;while (p != NULL){count++;if (count == i){LNode* node = (LNode*)malloc(sizeof(LNode));node->data = e;pre->next = node;node->next = p;return;}//未到第i个数据节点pre = p;p = p->next;}}
}void Find_min(LNode*& L)
{if (L->next == NULL)return;else{LNode* minpre, * minp, * pre, * p;minpre = L;minp = L->next;pre = L->next;p = pre->next;while (p != NULL){if (p->data < minp->data){minpre = pre;minp = p;}pre = p;p = p->next;}printf("min:%d", minp->data);}
}void Delete_min(LNode*& L)//删除最小元素
{if (L->next == NULL)return;else{LNode* minpre, * minp;minpre = L;minp = L->next;LNode* pre, * p;pre = L->next;p = pre->next;while (p != NULL){if (p->data < minp->data){minpre = pre;minp = p;}pre = p;p = p->next;}minpre->next = minp->next;free(minp);}
}//D26就地逆置单链表
void Reverse(LNode*& L)
{LNode* p, * r;if (L->next == NULL)//空表,直接结束return;else{p = L->next;//先把p放在第一个数据节点上L->next=NULL;//再把头节点断链while (p != NULL)//同时判断p和r是否为空{r = p->next;p->next = L->next;L->next = p;//头插法结束p = r;//p,r最后指向同一个节点}}
}//D27将一个表拆分成两个表然后A表为奇数B表是偶数(位序相同
void Divid(LNode*& L, LNode*& A, LNode*& B)
{A = (LNode*)malloc(sizeof(LNode));B = (LNode*)malloc(sizeof(LNode));A->next = NULL;B->next = NULL;LNode* ra = A;LNode* rb = B;if (L->next == NULL)return;LNode* p = L->next;while (p != NULL){if (p->data % 2 == 0){rb->next = p;rb = p;p = p->next;}else{ra->next = p;ra = p;p = p->next;}}ra->next = NULL;rb->next = NULL;
}//删除无序单链表中的所有重复元素int main()
{int a[7] = { 2,3,4,4,6,4,2 };LNode* L;CreataLNode(L, a, 7);PrintALL(L);Delete_x(L, 4);printf("\n");PrintALL(L);printf("\n");Find_min(L);printf("\n");Insert_i(L, 3, 7);PrintALL(L);Reverse(L);printf("\n");PrintALL(L);printf("\n");LNode* A, * B;Divid(L, A, B);PrintALL(A);printf("\n");PrintALL(B);Delete_min(A);printf("删除后:\n");PrintALL(A);}2 删除单链表中所有为x的节点
#include <stdio.h>
#include <malloc.h>typedef struct LinkNode
{int data;struct LinkNode* next;
}LNode;void CreateList(LNode*& L, int a[], int n)
{L = (LNode*)malloc(sizeof(LNode));int i = 0;LNode* r = L;for (i; i < n; i++){LNode* node = (LNode*)malloc(sizeof(LNode));node->data = a[i];r->next = node;r = node;}r->next = NULL;
}void Delete_ALLx(LNode*& L, int x)
{if (L->next == NULL)//依旧先判断 空链返回return;else{LNode* pre, * p;//若删除必须pre和p两个指针pre = L;p = L->next;while (p != NULL)//仍然存在数据节点{if (p->data == x)//1 若与x相同{pre->next = p->next;//则修改pre的指向free(p);//释放数据节点p = pre->next;//重置p指针}else//x与data不等则正常向后走{pre = p;p = p->next;}}}
}void PrintALL(LNode* L)
{LNode* p = L->next;while (p != NULL){printf(" %d ", p->data);p = p->next;}
}int main()
{int a[8] = { 2,3,4,5,2,3,2,8 };LNode* L;CreateList(L, a, 8);PrintALL(L);Delete_ALLx(L, 2);printf("\n");PrintALL(L);
}

3 求两个单调递增单链表的交集 并形成单链表c
#include <stdio.h>
#include <malloc.h>typedef struct LinkNode
{int data;struct LinkNode* next;
}LNode;void CreateList(LNode*& L, int a[], int n)
{L = (LNode*)malloc(sizeof(LNode));int i = 0;LNode* r = L;for (i; i < n; i++){LNode* node = (LNode*)malloc(sizeof(LNode));node->data = a[i];r->next = node;r = node;}r->next = NULL;
}void Delete_ALLx(LNode*& L, int x)//删除所以值为x的元素
{if (L->next == NULL)//依旧先判断 空链返回return;else{LNode* pre, * p;//若删除必须pre和p两个指针pre = L;p = L->next;while (p != NULL)//仍然存在数据节点{if (p->data == x)//1 若与x相同{pre->next = p->next;//则修改pre的指向free(p);//释放数据节点p = pre->next;//重置p指针}else//x与data不等则正常向后走{pre = p;p = p->next;}}}
}LNode* Intersection(LNode* A, LNode* B)//求AB交集(AB是单增)
{if (A->next == NULL || B->next == NULL)return NULL;else{LNode* p, * q, * r;LNode* C = (LNode*)malloc(sizeof(LNode));C->next = NULL;r = C;//尾插p = A->next;q = B->next;//准备工作完成while (p != NULL && q != NULL){if (p->data < q->data)//小的往前走{p = p->next;}else if (p->data > q->data)//小的往前走{q = q->next;}else{LNode* node = (LNode*)malloc(sizeof(LNode));node->data = p->data;r->next = node;r = node;p = p->next;//同时向前走q = q->next;}}r->next = NULL;//头插法结束,尾指针->next置空return C;}
}void PrintALL(LNode* L)
{LNode* p = L->next;while (p != NULL){printf(" %d ", p->data);p = p->next;}
}int main()
{int a[8] = { 1,2,2,3,4,5,6,7 };int b[9] = { 1,2,3,4,5,6,7,8,9};LNode* L1, *L2;CreateList(L1, a, 8);CreateList(L2,b,9);printf("L1为:");PrintALL(L1);printf("\n");printf("L2为:");PrintALL(L2);printf("\n");LNode* C = Intersection(L1, L2);printf("交集为:\n");PrintALL(C);}
核心代码
LNode* Intersection(LNode* A, LNode* B)//求AB交集(AB是单增)
{if (A->next == NULL || B->next == NULL)return NULL;else{LNode* p, * q, * r;LNode* C = (LNode*)malloc(sizeof(LNode));C->next = NULL;r = C;//尾插p = A->next;q = B->next;//准备工作完成while (p != NULL && q != NULL){if (p->data < q->data)//小的往前走{p = p->next;}else if (p->data > q->data)//小的往前走{q = q->next;}else{LNode* node = (LNode*)malloc(sizeof(LNode));node->data = p->data;r->next = node;r = node;p = p->next;//同时向前走q = q->next;}}r->next = NULL;//头插法结束,尾指针->next置空return C;}
}
一个非常重要的判断条件!
你的求交集函数Intersection可能存在一个逻辑错误,导致在某些情况下可能访问空指针,具体问题分析如下:
问题所在:循环条件错误
函数中使用的循环条件是:
while (p != NULL || q != NULL) // 错误的循环条件
这个条件的含义是 “当p或q任意一个不为空时继续循环”。但在单链表A和B是递增的前提下,当其中一个链表遍历完毕(p或q为空)时,另一个链表剩余的元素必然更大(因为链表递增),不可能再存在交集元素。此时继续循环会导致:
- 若
p已为空(q非空),后续执行p->data会访问空指针,引发程序崩溃。 - 若
q已为空(p非空),后续执行q->data会访问空指针,引发程序崩溃。
解决方案:修正循环条件
正确的循环条件应该是 “当p和q都不为空时才继续循环”,即: 使用【与】条件!
while (p != NULL && q != NULL) // 正确的循环条件
这样,当任意一个链表遍历完毕(p或q为空)时,循环会终止,避免访问空指针。
4 求无序链表AB的交集
#include <stdio.h>
#include <malloc.h>typedef struct LinkNode
{int data;struct LinkNode* next;
}LNode;void CreateList(LNode*& L, int a[], int n)
{L = (LNode*)malloc(sizeof(LNode));int i = 0;LNode* r = L;for (i; i < n; i++){LNode* node = (LNode*)malloc(sizeof(LNode));node->data = a[i];r->next = node;r = node;}r->next = NULL;
}void Delete_ALLx(LNode*& L, int x)//删除所以值为x的元素
{if (L->next == NULL)//依旧先判断 空链返回return;else{LNode* pre, * p;//若删除必须pre和p两个指针pre = L;p = L->next;while (p != NULL)//仍然存在数据节点{if (p->data == x)//1 若与x相同{pre->next = p->next;//则修改pre的指向free(p);//释放数据节点p = pre->next;//重置p指针}else//x与data不等则正常向后走{pre = p;p = p->next;}}}
}LNode* Intersection1(LNode* A, LNode* B)//求AB交集(AB是单增)
{if (A->next == NULL || B->next == NULL)return NULL;else{LNode* p, * q, * r;LNode* C = (LNode*)malloc(sizeof(LNode));C->next = NULL;r = C;//尾插p = A->next;q = B->next;//准备工作完成while (p != NULL && q != NULL){if (p->data < q->data)//小的往前走{p = p->next;}else if (p->data > q->data)//小的往前走{q = q->next;}else{LNode* node = (LNode*)malloc(sizeof(LNode));node->data = p->data;r->next = node;r = node;p = p->next;//同时向前走q = q->next;}}r->next = NULL;//头插法结束,尾指针->next置空return C;}
}LNode* Intersection2(LNode* A, LNode* B)
{if (A->next == NULL || B->next == NULL)return NULL;else{LNode* C = (LNode*)malloc(sizeof(LNode));C->next = NULL;LNode* r = C;//尾插法LNode* p = A->next;while (p != NULL){LNode* q = B->next;while (q != NULL){if (p->data != q->data){q = q->next;}else{LNode* node = (LNode*)malloc(sizeof(LNode));node->data = p->data;r->next = node;r = node;break;}}p = p->next;}r->next = NULL;return C;}
}void PrintALL(LNode* L)
{LNode* p = L->next;while (p != NULL){printf(" %d ", p->data);p = p->next;}
}int main()
{int a[8] = { 22,56,12,11,99,56,48,1 };int b[9] = { 1,2,55,12,48,77,22,46,99};LNode* A, * B, * C;CreateList(A, a, 8);CreateList(B, b, 9);C=Intersection2(A,B);PrintALL(C);printf("\n");}
