数据结构-C

数组

创建一维数组:

int *ans=(int*)malloc(sizeof(int)*numsSize)

创建二维数组

// 第一步 分配内存给二维数组
int** ans=(int**)malloc(sizeof(int*)*n);

// 第二步 分配内存给一维数组
for(int i=0;i<n;i++){
    ans[i]=(int*)malloc(sizeof(int)*n);
}

二分查找

在这里插入图片描述

int search(int* nums, int numsSize, int target){
    int l=0,r=numsSize-1;
    while(l<=r){
        int mid=(l+r)/2;
        if(nums[mid]>target){
            r=mid-1;
        }else if(nums[mid]<target){
            l=mid+1;
        }else{
            return mid;
        }
    }
    return -1;
}

移除元素

在这里插入图片描述

// 快指针遍历整个数组,不等于移除元素时就赋值给慢指针.
int removeElement(int* nums, int numsSize, int val){
    int slow=0;
    for(int fast=0;fast<numsSize;fast++){
        if(nums[fast]!=val){
            nums[slow++]=nums[fast];
        }
    }
    return slow;
}

有序数组的平方和

在这里插入图片描述


int* sortedSquares(int* nums, int numsSize, int* returnSize){
    *returnSize=numsSize;
    // 创建新的数组
    int*ans=(int*)malloc(sizeof(int)*numsSize);
    // 逆向赋值给新数组
    int k=numsSize-1; 
    // 双指针一头一尾
    int i=0,j=numsSize-1;
    // 比较两侧的平方和,将平方和大的赋值给新数组,并移动指针
    for(int index=numsSize-1;index>=0;index--){
        int leftSquare=nums[i]*nums[i];
        int rightSquare=nums[j]*nums[j];
        if(leftSquare<rightSquare){
            ans[k--]=rightSquare;
            j--;
        }else{
            ans[k--]=leftSquare;
            i++;
        }
    }
    return ans;
}

最短子数组

在这里插入图片描述

int minSubArrayLen(int target, int* nums, int numsSize){
    int res=INT_MAX;
    int i=0; //起点
    int sum=0; //片段和
    for(int j=0;j<numsSize;j++){ //终点
        sum+=nums[j];
        while(sum>=target){
            int sublen=j-i+1; //截取长度
            res=res<sublen?res:sublen; //更新最小长度
            sum-=nums[i++]; //移动起点,相当于窗口往前移动
        }
    }
    return res==INT_MAX?0:res;
}

蛇形矩阵

在这里插入图片描述

int** generateMatrix(int n, int* returnSize, int** returnColumnSizes){
    *returnSize=n;
    *returnColumnSizes=(int*)malloc(sizeof(int)*n);

    // 创建二维数组 ans 
    // 第一步 分配内存给二维数组
    int** ans=(int**)malloc(sizeof(int*) * n);

    // 第二步 分配内存给一维数组
    for(int i=0;i<n;i++){
        ans[i]=(int*)malloc(sizeof(int) *n);
        (*returnColumnSizes)[i]=n;
    }
    int cnt=1; //填入的数字
    int loop=n/2; //循环圈数
    int offset=1; //边界
    int startx=0,starty=0; //第一圈从(0,0)开始填入

    while(loop-->0){
        int i=startx,j=starty;
        // 上方从左到右
        for(j=starty;j<n-offset;j++){
            ans[startx][j]=cnt++;
        }
        // 右侧从上到下
        for(i=startx;i<n-offset;i++){
            ans[i][j]=cnt++;
        }
        // 下侧从右到左
        for(;j>starty;j--){
            ans[i][j]=cnt++;
        }
        // 左侧从下到上
        for(;i>startx;i--){
            ans[i][j]=cnt++;
        }
        // 下一圈从(1,1)开始填
        startx++;
        starty++;

        offset++;
    }

    // 中间单独填
    if(n%2){
        ans[n/2][n/2]=cnt;
    }
    return ans;
}

链表

设计链表

在这里插入图片描述

// 1.链表定义
typedef struct MyLinkedList{
    int val;
    struct MyLinkedList*next;
} MyLinkedList;


// 2.链表初始化
MyLinkedList* myLinkedListCreate() {
    // 虚拟头节点
    MyLinkedList*head=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    head->next=NULL;
    return head;
}


// 3.获取下标对应的节点值
int myLinkedListGet(MyLinkedList* obj, int index) {
    MyLinkedList*cur=obj->next; //从虚拟节点的下一个节点(头节点)开始遍历
    for(int i=0;cur!=NULL;i++){
        if(i==index){
            return cur->val;
        }else{
            cur=cur->next;
        }
    }
    return -1;
}


// 4.添加到头节点
void myLinkedListAddAtHead(MyLinkedList* obj, int val) {
    // 为要添加的节点分配内存空间
    MyLinkedList* cur=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    cur->val=val;
    // 连接 obj--cur--head
    cur->next=obj->next;
    obj->next=cur;
}

// 5.添加到尾部

// cur遍历到最后一个节点
void myLinkedListAddAtTail(MyLinkedList* obj, int val) {
    MyLinkedList* cur=obj;
    while(cur->next!=NULL){
        cur=cur->next;
    }
    MyLinkedList* tail=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    tail->val=val;
    // cur--tail--null
    tail->next=NULL;
    cur->next=tail;
}

// 6.在下标为index的节点前插入节点

// 先创建cur,定位到目标节点的前一个节点,插入时的位置关系为 cur--addNode--cur->next

void myLinkedListAddAtIndex(MyLinkedList* obj, int index, int val) {
    // 特判,添加到头节点
    if(index==0){
        myLinkedListAddAtHead(obj,val);
        return;
    }
    //遍历节点,用于定位到目标节点的前一个节点
    MyLinkedList* cur=(MyLinkedList*)malloc(sizeof(MyLinkedList));
    cur=obj->next;
    for(int i=1;cur!=NULL;i++){
        if(i==index){
            MyLinkedList* addNode=(MyLinkedList*)malloc(sizeof(MyLinkedList));
            addNode->val=val;

            addNode->next=cur->next;
            cur->next=addNode;
        }else{
            cur=cur->next;
        }
    }
}



// 7.删除下标为index的节点

// 特判删除头节点 obj->next=obj->next->next
// 遍历到目标节点的前一个节点cur,cur->next=cur->next->next,删除前要判断节点是否为空
void myLinkedListDeleteAtIndex(MyLinkedList* obj, int index) {
    //特判,删除头节点
    if(index==0){
        MyLinkedList* temp=obj->next; //原来的头节点
        if(temp!=NULL){
            obj->next=obj->next->next;
            free(temp);
        }
        return;
    }
    MyLinkedList* cur=obj->next;
    for(int i=1;cur!=NULL;i++){
        if(i==index){
            MyLinkedList* temp=cur->next; //要删除的节点
            if(temp!=NULL){
                cur->next=cur->next->next;
                free(temp);
            }
            return;
        }else{
            cur=cur->next;
        }
    }
}


// 8.释放节点
void myLinkedListFree(MyLinkedList* obj) {
    while(obj!=NULL){
        MyLinkedList *temp=obj;
        obj=obj->next;
        free(temp);
    }
}

/**
 * MyLinkedList* obj = myLinkedListCreate();
 * int param_1 = myLinkedListGet(obj, index);
 
 * myLinkedListAddAtHead(obj, val);
 
 * myLinkedListAddAtTail(obj, val);
 
 * myLinkedListAddAtIndex(obj, index, val);
 
 * myLinkedListDeleteAtIndex(obj, index);
 
 * myLinkedListFree(obj);
*/

移除元素

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeElements(struct ListNode* head, int val){
    typedef struct ListNode ListNode;
    //虚拟头结点
    ListNode *dummyHead; 
    dummyHead=(ListNode*)malloc(sizeof(ListNode));
    dummyHead->next=head;
    //指针cur从虚拟头结点开始遍历到要删除节点的前一个节点
    ListNode *cur=dummyHead; 
    while(cur->next!=NULL){
        if(cur->next->val==val){ 
            ListNode*temp=cur->next; //保存要去除的节点
            cur->next=cur->next->next;
            free(temp); //释放内存
        }else{
            cur=cur->next;
        }
    }
    head=dummyHead->next; //新的头结点
    free(dummyHead); //释放虚拟头结点
    return head;
}

翻转链表

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* reverseList(struct ListNode* head){
    struct ListNode*temp; //保存下一个节点
    struct ListNode*cur=head; //指向头节点
    struct ListNode*pre=NULL;
    //pre---cur---temp 交换后 temp--cur---pre
    while(cur!=NULL){
        temp=cur->next; //先保存下一个节点
        cur->next=pre; //下一个节点指针指向前一个节点
        // 同时向前移动
        pre=cur;
        cur=temp;
    }
    return pre;
}

两两交换链表节点

在这里插入图片描述
在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* swapPairs(struct ListNode* head){
    typedef struct ListNode ListNode;
    ListNode* dummyHead=(ListNode*)malloc(sizeof(ListNode));
    dummyHead->next=head;
    ListNode* cur=dummyHead;
    // 以cur 1 2 3 4为例
    while(cur->next!=NULL && cur->next->next!=NULL){
        ListNode* temp1=cur->next; //temp1保存节点1
        ListNode* temp2=cur->next->next->next; //temp2保存节点3

        cur->next=cur->next->next; //cur 2 
        cur->next->next= temp1; //cur 2 1
        cur->next->next->next= temp2; //cur 2 1 3

        cur=cur->next->next; //cur移动到第二组的头节点,节点2的位置
    }
    head=dummyHead->next;
    free(dummyHead);
    return head;
}

删除倒数第N个节点

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
    typedef struct ListNode ListNode;
    ListNode* dummyHead=(ListNode*)malloc(sizeof(ListNode));
    dummyHead->next=head;
    ListNode* fast=dummyHead;
    ListNode* slow=dummyHead;
    while(n-- && fast!=NULL){ //fast指针走n步
        fast=fast->next;
    }
    fast=fast->next; //fast指针走了n+1步
    while(fast!=NULL){
        fast=fast->next;
        slow=slow->next;
    }
    //此时slow走到要删除节点的前一个节点
    slow->next=slow->next->next;
    head=dummyHead->next;
    free(dummyHead);
    return head;
}

相交节点

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    typedef struct ListNode ListNode;
    ListNode* curA=NULL;
    ListNode* curB=NULL;
    int lenA=0,lenB=0,gapLen=0;

    curA=headA;
    while(curA!=NULL){
        lenA++;
        curA=curA->next;
    }
    curB=headB;
    while(curB!=NULL){
        lenB++;
        curB=curB->next;
    }
    
    if(lenA>lenB){
        curA=headA;
        curB=headB;
        gapLen=lenA-lenB;
    }else{
        curA=headB;
        curB=headA;
        gapLen=lenB-lenA;
    }

    while(gapLen--){
        curA=curA->next;
    }

    while(curA!=NULL){
        if(curA==curB){  //比较的是指针相等而不是数值相等,不能用curA->val==curB->val
            return curA;
        }
        curA=curA->next;
        curB=curB->next;
    }
    return NULL;
}

环形链表

在这里插入图片描述

在这里插入图片描述

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head) {
    typedef struct ListNode ListNode;
    ListNode *slow=head,*fast=head;
    while(fast && fast->next!=NULL){
        slow=slow->next;
        fast=fast->next->next;
        if(slow == fast){ //相遇
            ListNode *f=head,*l=fast; //f从起点出发,l从相遇点出发
            while(f!=l){
                f=f->next;
                l=l->next;
            }
            return f;
        }
    }
    return NULL;
}

栈和队列

双栈实现队列

在这里插入图片描述

在这里插入图片描述

typedef struct {
    int stackInTop,stackOutTop; //两个栈的栈顶指针
    int stackIn[100],stackOut[100];
} MyQueue;


MyQueue* myQueueCreate() {
    MyQueue* queue=(MyQueue*)malloc(sizeof(MyQueue));
    queue->stackInTop=0;
    queue->stackOutTop=0;
    return queue;
}

void myQueuePush(MyQueue* obj, int x) {
    obj->stackIn[(obj->stackInTop)++]=x;
}

int myQueuePop(MyQueue* obj) {
    int stackInTop=obj->stackInTop; //初始化栈顶指针
    int stackOutTop=obj->stackOutTop;

    if(stackOutTop==0){ //输出栈为空,则将输入栈的内容全部复制到输出栈
        while(stackInTop>0){
            obj->stackOut[stackOutTop++]=obj->stackIn[--stackInTop]; //注意是先--,后++
        }
    }

    int top=obj->stackOut[--stackOutTop]; //保存并弹出要出栈的元素
    
    while(stackOutTop>0){ //将输出栈的内容放回输入栈
        obj->stackIn[stackInTop++]=obj->stackOut[--stackOutTop];
    }

    obj->stackInTop=stackInTop; //更新栈顶指针
    obj->stackOutTop=stackOutTop;
    
    return top;
}

int myQueuePeek(MyQueue* obj) {
    return obj->stackIn[0]; //输入栈栈底元素为队头
}


bool myQueueEmpty(MyQueue* obj) {
    return obj->stackInTop==0 && obj->stackOutTop==0; //输入输出栈是否同时为空 
}

void myQueueFree(MyQueue* obj) {
    obj->stackInTop=0; //栈顶指针置为0
    obj->stackOutTop=0;
}

/**
 * Your MyQueue struct will be instantiated and called as such:
 * MyQueue* obj = myQueueCreate();
 * myQueuePush(obj, x);
 
 * int param_2 = myQueuePop(obj);
 
 * int param_3 = myQueuePeek(obj);
 
 * bool param_4 = myQueueEmpty(obj);
 
 * myQueueFree(obj);
*/

链表实现栈

在这里插入图片描述
在这里插入图片描述

//1. 定义链表节点的结构体
typedef struct tagListNode{    
    struct tagListNode* next;
    int val;
}ListNode;


//2. 定义栈顶的指针
typedef struct {     
    ListNode *top;   
} MyStack;

//3. 创建栈
MyStack* myStackCreate() {
    MyStack* stk=calloc(1,sizeof(MyStack)); //calloc()在堆区申请动态内存空间
    return stk;
}


//4. 入栈 node->next=obj->top 
void myStackPush(MyStack* obj, int x) {
    ListNode* node=(ListNode*)malloc(sizeof(ListNode));
    node->val=x;        // 赋值x

    node->next=obj->top; // 入栈新元素为新的栈顶
    obj->top=node; 
}

//5. 出栈 node指向原来的栈顶,obj->top=node->next
int myStackPop(MyStack* obj) {
    ListNode* node=obj->top; //指向栈顶
    int val=node->val; //出栈元素的值

    obj->top=node->next; //新的栈顶

    free(node);
    return val;
}

//6. 栈顶元素
int myStackTop(MyStack* obj) {
    return obj->top->val;
}

//7. 栈是否为空
bool myStackEmpty(MyStack* obj) {
    return (obj->top == NULL);
}

//8. 清空栈
void myStackFree(MyStack* obj) {
    while(obj->top != NULL){
        ListNode *node=obj->top;    //保存当前栈顶
        obj->top=node->next;    //清除当前栈顶
        free(node);
    }
    free(obj);
}

/**
 * Your MyStack struct will be instantiated and called as such:
 * MyStack* obj = myStackCreate();
 * myStackPush(obj, x);
 
 * int param_2 = myStackPop(obj);
 
 * int param_3 = myStackTop(obj);
 
 * bool param_4 = myStackEmpty(obj);
 
 * myStackFree(obj);
*/

括号匹配

在这里插入图片描述

//遇到右括号,取出栈顶比较,不匹配返回true
int notMatch(char par,char *stack,int top){
    switch(par){
        case '}':
            return stack[top-1]!='{';
        case ')':
            return stack[top-1]!='(';
        case ']':
            return stack[top-1]!='[';
    }
    return 0;
}

bool isValid(char * s){
    int top=0;
    char stack[5000];
    int len=strlen(s);
    for(int i=0;i<len;i++){
    	//左括号入栈
        if(s[i]=='{' || s[i]=='[' || s[i]=='(') 
            stack[top++]=s[i];
        //栈提前为空 或者 不匹配
        else if(top==0 || notMatch(s[i],stack,top))
            return 0;
        //匹配成功弹出
        else
            top--;
    }
    // 全部匹配成功则栈为空
    return top==0;
}

字母对对碰

在这里插入图片描述

//使用栈来保存遍历过的字母
char * removeDuplicates(char * str){
    int top=0;
    int len=strlen(str);
    // 栈大小多开一位,用来存放字符串末尾的'\0'
    char* stack=(char*)malloc(sizeof(char)* len+1);
    for(int i=0;i<len;i++){
    	//栈为空 或者 栈顶与当前遍历字母不同 
        if(top==0 || stack[top-1] != str[i])
            stack[top++]=str[i];	//入栈
        else
            top--; //相同则弹出
    }
    stack[top]='\0';	//字符串标志
    return stack;
}

逆波兰表达式求值

在这里插入图片描述

注意c语言中字符串以’\0’结尾,因此取操作数的时候要排除掉’\0’

bool isNumber(char* token){     //字符串以'\0'结尾,因此数字要取[0]处的值
    return strlen(token)>1 || '0'<=token[0] && token[0]<='9';
}

int evalRPN(char ** tokens, int tokensSize){
    int len=tokensSize;
    int stack[len],top=0;
    for(int i=0;i<len;i++){
        char * token=tokens[i]; //token指向单个字符串
        if(isNumber(token)){    //数字直接入栈
            stack[top++]=atoi(token);   //atoi将字符串转化为整数
        }else{
            int num2=stack[--top];
            int num1=stack[--top];
            switch(token[0]){   //token[0]为运算符,除开末尾的'\0'
                case '+':
                    stack[top++]=num1+num2;
                    break;
                case '-':
                    stack[top++]=num1-num2;
                    break;
                case '*':
                    stack[top++]=num1*num2;
                    break;
                case '/':
                    stack[top++]=num1/num2;
                    break;
            }
        }
    }
    return stack[top-1];
}

滑动窗口

在这里插入图片描述

  • 出队:只要遍历元素nums[i]大于等于队尾元素nums[q[right–]]时,队尾元素弹出。
  • 入队:直到nums[i]小于队尾才入队,保证队列对应的元素单调递减
  • 队列q存放的是下标,下标对应的元素单调递减,这样队头q[left]存放的是窗口最大值的下标
/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* maxSlidingWindow(int* nums, int numsSize, int k, int* returnSize){
    int q[numsSize];
    int left=0,right=0;  

    for(int i=0;i<k;i++){
        //当前元素大于等于队尾的元素,则将队尾弹出
        while(left<right && nums[i]>=nums[q[right-1]]){
            right--;
        }
        //小于则入队,保持队列单减
        q[right++]=i;
    }

    *returnSize=0;
    int *ans=malloc(sizeof(int)*numsSize-k+1);      //ans保存最大值数组
    ans[(*returnSize)++]=nums[q[left]];        //前K个元素的最大值
    
    for(int i=k;i<numsSize;i++){
        while(left<right && nums[i]>=nums[q[right-1]]){
            right--;
        }
        q[right++]=i;
        while(q[left]<=i-k){
            left++;     //窗口移动
        }
        ans[(*returnSize)++]=nums[q[left]];   //当前窗口最大值
    }
    return ans;
}

二叉树

二叉树定义

 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };

二叉树递归遍历

前序


void preOrder(struct TreeNode*root,int *res,int *returnSize){
    if(root==NULL){
        return;
    }
    res[(*returnSize)++]=root->val;		//根节点加入结果数组
    preOrder(root->left,res,returnSize);
    preOrder(root->right,res,returnSize);
}

int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int *res=(int*)malloc(sizeof(int)*100);
    *returnSize=0;
    preOrder(root,res,returnSize);
    return res;
}

中序


void inOrder(struct TreeNode* node,int* res,int* returnSize){
    if(node==NULL){
        return;
    }
    inOrder(node->left,res,returnSize);
    res[(*returnSize)++]=node->val;
    inOrder(node->right,res,returnSize);
}

int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int *res=(int*)malloc(sizeof(int)* 100);
    *returnSize=0;
    inOrder(root,res,returnSize);
    return res;    
}

后序


void postOrder(struct TreeNode* node,int* res,int* returnSize){
    if(node==NULL){
        return;
    }
    postOrder(node->left,res,returnSize);
    postOrder(node->right,res,returnSize);
    res[(*returnSize)++]=node->val;
}

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int *res=(int*)malloc(sizeof(int)* 100);
    *returnSize=0;
    postOrder(root,res,returnSize);
    return res;
}

二叉树层序遍历

在这里插入图片描述


int** levelOrder(struct TreeNode* root, int* returnSize, int** returnColumnSizes) {
    *returnSize=0;  //记录层数
    if(root==NULL)return NULL;

    int **res=(int**)malloc(sizeof(int*) * 2000);
    *returnColumnSizes=(int*)malloc(sizeof(int) * 2000);     //记录每一层的结点数
    
    struct TreeNode* queue[2000];
    struct TreeNode* cur;

    int front=0,rear=0;
    queue[rear++]=root;     //根节点入队

    while(front<rear){
        int colSize=0,last=rear;   
        res[*returnSize]=(int*)malloc(sizeof(int)*(last-front)); //保留每一层的结点
        
        while(front<last){
            cur=queue[front++];
            res[*returnSize][colSize++]=cur->val;   //记录当前层的结点
            if(cur->left!=NULL){
                queue[rear++]=cur->left;
            }
            if(cur->right!=NULL){
                queue[rear++]=cur->right;
            }
        }
        (*returnColumnSizes)[*returnSize]=colSize;  //记录当前层结点数
        (*returnSize)++;  //更新当前层数
    }
    return res;
}




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值